以下例子均以类class A为例
1.成员函数
其参数默认包含一个类类型的常量指针 A* const this,调用时该指针指向调用对象
const成员函数:在函数的参数列表后加上const,代表const成员函数(并非返回const对象)。带有const修饰的成员函数代表将this指针修饰为底层const,此时形参格式为const A* const this(即指针自身不可 修改,指针指向的对象也不可修改)好处是保证了成员函数对对象的修改限制,避免误操作。
2.构造函数与初始化
构造函数不可以被声明为const,一个const对象的const属性直到对象的构造函数完成后才生效,所以在构造函数运行的过程中,const对象可以被修改。
默认构造函数:一个没有定义构造函数的类将会有一个默认的构造函数,若已经定义构造函数,则默认函数会被自动取消,除非手动指定一个默认的构造函数(避免了不想要的默认构造函数的存在),如 A ( ) = default;
/*事实上,任何对象在被定义的时候都将进行初始化(试图默认初始化一个没有默认构造函数的对象的行为是非法的),有定义构造函数的将会调用构造函数,没有定义构造函数的将会调用默认构造函数
如果一个对象有成员,则其成员也将进行初始化(对于大部分的基本类型,其默认构造函数就是什么都不做,这也继承了C的特性)*/
构造函数的初始值列表(重点):
对于一个包含着类成员的类来说,初始化是一件需要细细考量的事情,对象的初始化可以说是一个金字塔结构,一个对象的初始化需要它所有成员的初始化。而在C++中,金字塔的底层是各种基本类型,他们都有着自己的默认构造函数(即使有些默认舒初始化的结果使我们不愿意看到的),即我们几乎不必担心类的初始化会触犯语法规则
但是在C++中有着引用特性,即在引用定义的同时必须显式初始化。同样的还有const
而构造函数,实际上是在对象定义并初始化完成后对对象的修改,这样就形成了问题:如何正确地初始化一个引用类型或const类型的成员呢?
一种方法是加上类内初始值,如
class A
{
const int &B=D;
string C;
const int D;
};
//这样将会把B引用为D
/*值得注意的是,无论是这样的先后顺序,或者const属性,都并不影响语法和结果的正确性*/
/*原因是类成员全部定义后(分配空间,给予内存位置索引)按内存顺序进行初始化,初始化完成后才加上const属性*/
class A
{
const int B=D;
string C;
const int D=1;
};
//这样初始化过后,B为一个不确定的值,而D=1,因为初始化B的时候D还未初始化
初始化的另一种方法是用初始化列表
class A
{
const int& B;
string C;
const int D;
A ( ) : C(""), D(1), B(D) { }
}
在定义构造函数时,在构造函数参数表和程序块之间用冒号后面接一串成员的初始化函数的调用。在C++中,列表初始化是与定义捆绑的,即类似于 int D=1; 而非 int D; D=1;
**对于列表初始化来说,成员的初始化函数的执行顺序 与 初始化列表中的成员的顺序 无关,与 成员在类内的定义顺序 有关**
在初始化一个成员的时候,若有列表初始化,则优先列表初始化,若无则用类内初始值
class A
{
const int B=1;
string C;
const int D=2;
A ( ) : C(""), D(4), B(D) { }
}//这样做,B为一个不确定值,而D=4