C++语法基础(二)

C++复合类型

结构体

  1. C++的结构,定义结构体类型的变量时,可以省略struct关键字

  2. 可以定义成员函数,在结构体中的成员函数内部可以直接访问本结构体的成员,无需通过"."或"->"

联合

  1. C++的联合,定义联合体类型的变量时,可以省略union关键字

  2. 支持匿名联合

  3. 重点:共用一块内存空间

枚举

  1. C++的枚举,定义枚举型的变量时,可以省略enum关键字

  2. 独立的类型,和整型之间不能隐式转换.

代码演示

cpp 复制代码
#include<iostream>
#include<cstring>
using namespace std;

void testStruct(){
    struct Student{
        int m_age;
        char m_name[128];
        void getInfo(){
            cout << m_name << ":" << m_age << endl;
        }
    };
    /*struct*/ Student s1;
    s1.m_age = 18;
    strcpy(s1.m_name, "林枫");
    s1.getInfo();
    cout << "姓名:" << s1.m_name << ", 年龄:" << s1.m_age << endl;
}
void testUnion(){
    union /*A*/{//匿名联合主要想体现 成员的内存排布方式(共用同一块内存空间)
        int i;
        char c[4];
    };
    //Union A a;  //C语言写法
    //A a;        //C++写法
    i = 0x12345678;
    //cout << c[0] << ' ' << c[1] << ' ' << c[2] 
    //        << ' ' << c[3] << endl;//输出对应字符
    cout << hex << (int)c[0] << ' ' << (int)c[1] << ' ' << (int)c[2]
            << ' ' << (int)c[3] << endl;
}
void testEnum(){
    enum Color{ red,green,blue };
    //C语言写法
    //enum Color c = red// 0-err//枚举类型不支持隐式转换
    //C++写法
    Color c = red;
    Color d = green;
    Color e = blue;
    cout << "c = " << c << endl;
    cout << "d = " << d << endl;
    cout << "e = " << e << endl;
}
void testBool(){
    bool a = true;//"";"fddgd"
    bool b = false;"0.0000";"123";NULL;
    cout << "a = " << a << ", b = " << b << endl;
    cout << boolalpha << "a = " << a << ", b = " << b << endl;
}
int main(){
    testStruct();
    testUnion();
    testEnum();
    testBool();
    return 0;
}

布尔类型

表示布尔量的数据类型

-->bool

布尔类型的字面值常量

-->true表示真 -->false表示假

布尔类型的本质 - 单字节整数

用1和0表示真和假

任何基本类型都可以被隐式转换为布尔类型

非0即真,0即假

代码演示

cpp 复制代码
#include<iostream>
using namespace std;

void testBool(){
    bool a = true;//"";"fddgd"
    bool b = false;"0.0000";"123";NULL;
    cout << "a = " << a << ", b = " << b << endl;
    cout << boolalpha << "a = " << a << ", b = " << b << endl;
}
int main(){
    testBool();
    return 0;
}

函数关系--重载

重载关系

-->同一作用域内,函数名相同,参数表不同

-->根据实参类型和形参的类型进行匹配,调用最匹配的函数

-->只有同一作用域内的同名函数才涉及重载的关系,不同作用域的同名函数涉及的是隐藏关系。

重载解析

-->完全匹配>常量转换>升级转换>标准转换>自定义转换>省略号匹配

-->函数指针的类型决定其调用的重载函数的版本

重载关系

代码演示(重载匹配)

cpp 复制代码
//重载关系: 1.同一作用域内 2.函数名相同 3.参数列表不同
//形参表是否相同,与参数名无关,与形参个数, 以及,每一个对应的参数类型有关
#include <iostream>
using namespace std;
void foo(char* c,short s){
    cout << "1.foo" << endl;
}
void foo(int i,double d){
    cout << "2.foo" << endl;
}
void foo(const char* c,short s){
    cout << "3.foo" << endl;
}
void foo(double d,int i){
    cout << "4.foo" << endl;
}

//int foo(double i,int d){} //错误,形参表相同,是否构成重载关系与返回值类型无关
int main(){
    char* c;
    short s;
    foo(c,s);//1
    const char* cc;//3
    foo(cc,s);
    int i;double d;
    foo(d,i);//4
    foo(i,d);//2
    return 0;
}

代码演示(不同作用域下的重载关系)

cpp 复制代码
//不同作用域的同名函数涉及的是隐藏关系
#include <iostream>
using namespace std;
namespace ns1{
    void foo(char* c,short s){
        cout << "1.foo" << endl;
    }
    void foo(int i,double d){
        cout << "2.foo" << endl;
    }
}
namespace ns2{
    void foo(const char* c,short s){
        cout << "3.foo" << endl;
    }
    void foo(double d,int i){
        cout << "4.foo" << endl;
    }
}

int main(){
    using namespace ns1;//ns1中foo出现在可见表中
    using ns2::foo;//ns2中foo出现在定义表中
    char* c;
    short s;
    foo(c,s);//3
    return 0;
}

重载解析

代码演示(重载解析优先级)

cpp 复制代码
//重载解析优先级
#include<iostream>
using namespace std;

void foo(char* c, short s){  //完全匹配 _Z3fooPcs
    cout << "1.foo" << endl;
}
void foo(const char*, short s){  //常量转换 _Z3fooPKcs
    cout << "2.foo" << endl;
}
void foo(char* c, int s){
    cout << "3.foo" << endl;  //升级转换 _Z3fooPci
}
void foo(char* c, char s){    //标准转换 _Z3fooPcc
    cout << "4.foo" << endl;
}
void foo(...){  //省略匹配  _Z3fooz
    cout << "5.foo" << endl;
}

int main(){
    char* c;
    short s;
    foo(c,s);//普通方式调用,由实参和形参的匹配度来决定调用哪个foo函数
    void(*pfunc)(const char* c,short s) = foo;//_Z3fooPKcs
    pfunc(c,s);//函数指针方式调用,由函数指针本身的类型决定调用哪个foo函数
    return 0;
}

重载的本质--"换名机制"

Z --表示自定函数系统默认前缀

P --表示指针

c --char类型

s --short类型

K --const类型

z --表示可变长参数

屏蔽C++"换名机制"--extern "C"

通过****extern "C"可以要求C++编译器按照C方式编译函数,即不做换名

原函数
cpp 复制代码
  int sum(int a,int b){
        return a + b;
    }

    int sub(int a, int b){
        return a - b;
    }
查看符号表
bash 复制代码
tern$vi cal.cpp
11_extern$g++ -c cal.cpp
11_extern$ls
a.out  cal.cpp  cal.o  libcal.a  main.c  main.o
11_extern$ar -r libcal.a cal.o
11_extern$nm libcal.a

cal.o:
0000000000000014 T _Z3subii
0000000000000000 T _Z3sumii
使用extern "C"
cpp 复制代码
extern "C"{
    int sum(int a,int b){
        return a + b;
    }

    int sub(int a, int b){
        return a - b;
    }
}
查看符号表
bash 复制代码
11_extern$g++ -c cal.cpp 
11_extern$ls
a.out  cal.cpp  cal.o  main.c  main.o
11_extern$ar -r libcal.a cal.o
ar: 正在创建 libcal.a
11_extern$ls
a.out  cal.cpp  cal.o  libcal.a  main.c  main.o
11_extern$nm libcal.a

cal.o:
0000000000000014 T sub
0000000000000000 T sum
11_extern$

缺省参数

1. 可以为函数的形参指定缺省(默认)值,当调用该函数时若未指定实参,则使用形参的缺省(默认)值。
2. 如果函数的某一个形参具有缺省(默认)值,那么该形参后面的所有形参必须都具有缺省(默认)值
3. 尽量避免因为使用缺省参数而导致重载匹配歧义
4. 函数形参的缺省(默认)值只能在函数声明中指定

cpp 复制代码
//缺省(默认)参数:带默认值的形参
//默认值不是初始值
#include<iostream>
using namespace std;
void foo(int a, double b=3.14, float c=2.0, short d=1, char e = 'A');
void foo(int a){
}
void foo(int a, double b, float c, short d, char e) {
    // 函数实现
    cout << "e = " << e << endl;
}
int main(){

    foo(1,2,3.0,4);
    foo(1,2,3.0,4,'B');
    //foo(10);//造成重载匹配歧义
    return 0;
}
相关推荐
网易独家音乐人Mike Zhou3 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
‘’林花谢了春红‘’4 小时前
C++ list (链表)容器
c++·链表·list
搬砖的小码农_Sky6 小时前
C语言:数组
c语言·数据结构
机器视觉知识推荐、就业指导6 小时前
C++设计模式:建造者模式(Builder) 房屋建造案例
c++
为什么每天的风都这么大7 小时前
Vscode/Code-server无网环境安装通义灵码
ide·vscode·阿里云·编辑器·ai编程·code-server
Yang.998 小时前
基于Windows系统用C++做一个点名工具
c++·windows·sql·visual studio code·sqlite3
熬夜学编程的小王8 小时前
【初阶数据结构篇】双向链表的实现(赋源码)
数据结构·c++·链表·双向链表
zz40_8 小时前
C++自己写类 和 运算符重载函数
c++
六月的翅膀8 小时前
C++:实例访问静态成员函数和类访问静态成员函数有什么区别
开发语言·c++