- 声明式是告诉编译器某个东西的名称和类型。
- 签名式是指参数和返回值。一个函数的签名等同于该函数的类型(C++对签名式的官方认定不包括返回值)
将函数声明为 explicit ,可以阻止他们被用来执行隐式转换,但他们仍可以用来进行下你是类型转换
其他静态成员只能在类里边进行声明,类外进行初始化。格式为: 类域::类型 变量名 = 初始值
- 类的静态常量成员可以在类里边进行初始化(static const int a =
10),但是尽管在类里边进行了初始化,但是在类里边进行的也只是声明。如果只是使用这个常量的值的话就只要有这个带初始值的声明就OK了,如果想要去这些常量的地址的话还需要在类外进行定义,需要注意的是,尽管在类里边的只是声明,但是,该静态常量已经被赋初值了,在类外进行定义的时候不能再给他赋值。还需注意的是类外的定义需要放到实现文件中而不是头文件中。 - 对#define 和 enum常量取地址是不合法的。
- 如果两个函数除了常量性不同(一个使用const修饰,另一个没有使用const修饰),这两个函数也是构成了重载。
- 在const修饰类成员函数,实际上修饰隐含的this指针,表示在类中不可以修改类的任何非静态成员变量。就算是在const修饰的成员函数里边,静态成员变量也是可以被修改的(除非把静态成员变量声明为const),其他普通数据成员是不能被修改的。
- 如果想要在const修饰的成员函数里边修改类的数据成员,该成员定义声明时必须加上mutable关键字。
- 对于[ ]重载,如果给出了两个版本(const修饰和没有const修饰),两个函数实现的功能基本一样,只是const修饰的不允许他的返回值被修改,为了解决两个函数内容重复的问题,可以在将其中一个函数的实现改成调用另一个函数,而这个调用必须是安全的,所以,只有使用没有const修饰的去调用const修饰的那个函数。调用非const函数的是非const对象,调用const函数的是const对象,在非const函数里边调用同名的const函数肯定没法成功,因为对象是非const的,肯定会默认调用非const函数,如果不做任何的处理,非const函数实现的就是递归调用自己,还是无限调用自己的,为了解决这个问题,使用const_cast将其this指针转换成const,这样的话,才能实现调用const函数,还有一个问题要解决,非const函数的返回值是可以修改的,现在使用const_cast进行转化并调用了const函数,它的值就没法修改了,为了解决这个问题,还需要进行一次转换,那就是使用static_cast转换,因为即使是在const函数内部,也是可以修改静态成员的。
- 定义一个迭代器的时候使用一个const修饰,const修饰的就是这个迭代器本身,即不能对该迭代器进行自增或减减操作。
eg: const std::vector iterator iter = vec.begin() 不能进行++iter 但*iter = 10;是可以的。
- 如果想要定义一个迭代,是迭代器“指向”的内容不能改变,需要在定义时直接定义一个const类型的迭代器
eg:std::vector const_iterator iter = vec.begin() ,不能进行 *iter = 10; 但可以自增或减减
- const对象可以调用const成员函数,不能调用非const成员函数
非const对象既可以调用非const成员函数,又可以调用const成员函数
const成员函数可以调用其他const成员函数,但是不能调用其他非const成员函数,因为const成员函数承诺不修改任何成员变量,而在其内部调用的非从头成员函数并没有这样的承诺 - 非const成员函数既可以调用const成员函数,又可以调用非const成员函数。
C++规定对象的成员函数的初始化动作发生在进入构造函数本体之前。在构造函数的函数体里边对对象的每个成员赋值不叫初始化,只能叫做赋值。
在构造函数的初始化列表内对类的成员变量进行初始化比在函数体内对成员变量进行赋值效率要高。因为在函数体里边对成员变量进行赋值的话,会在进入函数体内之前调用默认的构造函数对成员进行初始化,然后再在函数体里边对这些成员变量进行赋值。 - 对于内置类型,初始化和赋值的成本是一样的。
- 初始化列表必须对类的所有成员变量进行初始化,并且每个成员在初始化列表中出现且仅出现一次。为什么?
必须在类的初始化列表里边进行初始化的成员:
引用数据成员。因为引用一旦定义完成就没法再绑定其他对象,所以必须在初始化列表中就将引用与对应的对象绑定。
- const数据成员。const修饰的成员的值是不能修改的,不能对它进行复制操作,只能在初始化列表对其进行初始化。
- 类类型的成员。(该类没有缺省的构造函数)。
- 构造函数的作用
1、构建对象
2、初始化对象
3、类型转换
- C++对“定义于不同编译单元内的non-local static对象”的初始化相对次序并无明确定义。
- 为了避免使用一个跨编译单元的对象来初始化另一个对象中两个对象初始化顺序不确定的问题,可以使用local static来替换non-local static对象。