2.结构体,联合以及枚举的使用
2.1 结构体在C++中的不同
C语言中:struct Person{
char name[20];
int age;
};
struct Person p = {"zhangfei",30};一般使用起别名的方式解决名字过长的问题
C++中:
struct Person{
string name;
int age;
};
Person p = {"zhangfei",30};
区别:
(1)定义结构体变量的时候,可以省略struct关键字
(2)可以在结构体中定义函数,并且函数去访问结构体中的变量时不需要 .->之类的,但是如果调用结构体中的函数,就需要结构体变量/指针 使用 ./->来调用相关函数
提问:不同的结构体变量调用相同的函数执行结果不同,这是为什么?
实际上在调用函数的过程中隐含的传递了一个看不见的实参;
2.2 联合在C++中的不同
(1) 在C++中使用联合定义变量时,union关键字可以省略 ;如: union Un{。。。。。};Un u;(2) 支持匿名联合 ; 如:union { ......};
2.3 枚举在C++中的不同
(1)枚举类型在定义变量时可以省略关键字enum; 如:enum En{。。。。。}; En e;(2)C++中枚举类型是一种独立的数据类型,不能直接用整型赋值
C语言中枚举类型本质上就是整型,可以使用整型赋值
3.布尔类型和以及运算符别名
3.1 布尔类型
C中的bool类型不是C语言本身的基本数据类型 #include<stdbool.h>C++ 中的本身有bool 类型,bool类型的值有两种:true 和 false ,数值为 1 和 0,本质上就是单字节整数,
任何基本数据类型都可以隐式转换为bool类型
使用 boolalpha来设置bool类型的输出样式为 : true 和 false
小结:
bool类型可以定义变量,可以作为函数的参数,也可以作为函数的返回值,并且bool类型也可以定义指针类型,如
bool sex = true; bool* p1 = &sex;
3.2 运算符别名
&& = and; || = or; & = bitand; | = bitor;等等4. C++ 中的函数的特性
4.1 函数的重载
(1) 概念:在同一个作用域中,函数名相同,参数列表不同的函数之间构成重载关系(overload)(2)重载主要方式:
a. 函数的参数类型不同
b. 函数的参数个数不同
c. 函数的参数顺序不同
d. const修饰的常函数和普通函数构成重载(以后讲到)
(3)比较特殊的函数重载
namespace ns1{show(int i){}}
namespace ns2{show(double j){}}
对于不同命名空间中的函数,如果使用命名空间指令的方式导入可能构成重载(如:
using namespace ns1;
using namespace ns2;
show(100);show(3.14);//构成重载),
如果使用名字空间声明的方式导入,产生隐藏 (如:
using ns1::show; //类似于局部优先法则,将show函数隐藏起来了,不再构成重载
using ns2::show; //这种导入方式与上面的导入方式同级别,再次构成重载)
见代码:11overload.cpp
(4)重载匹配的原则
完全匹配 > 常量转换 > 升级转换 > 标准转换(int -> char 等) > 自定义转换(以后说) > 省略号匹配
4.2 重载的原理
(1)C++ 编译器是通过对函数进行换名,将参数表信息体现在函数名中,从而构成重载 : 如void show(int s){}
show -> Z4showi
(2)如何将C 程序 和 C++进行结合?
a. C程序可以通过调用C++编译器换名后的新函数名调用C++程序中的函数
nm xxx.o 查看二进制文件中的函数名
b. 通过extern "C" 可以明确要求C++编译器不要对函数进行换名操作,
如果不想换名的内容比较多,那么使用extern "C"{}括起来即可
5.函数的相关特性
5.1 缺省参数
(1)概念C语言中:
如: void fn(int i){}; ==>fn(100);//C语言中要求使用fn必须传实参
C++语言中:
void fn(int i = 100){}; ==>fn(100);---->i = 200;
==>fn(); ---->i = 100;
小结:
如果函数的形参有缺省值,当函数调用时没有传递实参,那么形参就使用缺省值,
如果调用函数时传递了实参,那么形参就使用实参的值;
(2)注意问题
a.缺省参数必须靠右,如果一个函数有多个参数,并且部分参数有缺省值,那么有缺省值的参数必须靠右
如:
int fn(int i,char c = 'a'){}//ok
==>fn(10);
==>fn(10,'b')
int fn(int i = 10,char c){}//error
==>fn('a');//error
b.如果函数的声明和定义分开,那么缺省参数只能写在函数的声明部分
如:
函数的声明:int fn(int i = 10);
函数的定义:int fn(int i){}
c.注意防止重载的冲突 如:见代码1
d. C中 和 C++中函数的潜规则
如: void fn(){} //在C语言中表示可以接受任意多个任意类型的参数,在C++中表示不能接受任何参数(否则可能构成重载),一般采用void 表示不需要传递参数,如void fn(void){} //见代码 02
1.2 哑元
只有数据类型没有名称的参数叫做 哑元,这样的函数叫做 哑元函数如:
void fn(int i){} //普通函数
void fn(int){} // 哑元函数
用途:
(1) 兼容以前的代码
void fn(int i){ ......}
==> fn(); //error
==> fn(10); //虽然没有用 也要传递一个int 实参
(2)用于自增自减运算符重载的区别(以后讲到)
前++: operator++(int)
后++: operator++
1.3 内联函数
使用关键字inline 关键字修饰的函数叫做内联函数,但是不会像宏一样进行简单的替换,而是经过分析之后的指令替换相对于宏的优势:计算实参表达式的值,类型检查等;例子:见代码 03;注意:
inline 只是一种建议而不是要求,使用inline修饰的函数不一定发生内联处理,
当然即使没有使用inline 关键字修饰也可能发生内联,主要取决于编译器的处理;
g++ -S 03inline.cpp //生成.s的汇编文件,如果做了内联处理将看不到自定义的函数,否则用下面的命令
g++ -S -O 03inline.cpp //生成.s 的汇编文件并且对程序做优化处理,应该就会看到内联处理的效果