c++成员变量、构造函数初始化问题

c++成员变量初始化

普通变量

在构造函数中进行赋值,如果考虑效率的话,在构造函数的初始化列表中进行赋值。

static变量

static变量属于类所有,不属于任何一个对象。在类中,static成员函数也属于类所有,所以这个函数不接受this指针,因此只能访问static成员变量。

const常量变量

const常量需要在声明的时候即初始化。因此需要在变量创建的时候进行初始化。一般采用在构造函数的初始化列表中对const变量进行初始化。

引用

引用型变量和const变量类似。需要在创建的时候即进行初始化。也是在初始化列表中进行。但需要注意用Reference类型。

1
2
3
4
5
6
7
8
9
10
class A
{
private:
int a;
int & b;
public:
///必须使用初始化列表
A():b(&a){}
A(int & c):b(c){}
};

const static integral 变量

对于既是const又是static 而且还是整形变量,可以直接在类的定义中初始化,但是初始化值必须是常量表达式

1
2
3
4
5
class A
{
private:
const static int q = 0; ///可以直接在初始化
};

注意:
C++11的基本思想是,允许非静态(non-static)数据成员在其声明处(在其所属类内部)进行初始化。这样,在运行过程中,需要初始值时构造函数可以使用这个初始值。

构造函数的调用顺序

1
2
3
4
5
6
首先,任何虚拟基类的构造函数按照它们被继承的顺序构造;
其次,任何非虚拟基类的构造函数按照它们被继承的顺序构造;
然后,任何成员对象的构造函数按照它们声明的顺序调用;
最后,是本类的构造函数

析构函数的为“逆构造函数”,其析构顺序和构造函数相反
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <iostream>
using namespace std;
class OBJ1{
public:
OBJ1(){ cout<<"OBJ1\n"; }
~OBJ1(){ cout<<"~OBJ1\n"; }
};
class OBJ2{
public:
OBJ2(){ cout<<"OBJ2\n";}
~OBJ2(){ cout<<"~OBJ2\n";}
};
class Base1{
public:
Base1(){ cout<<"Base1\n";}
~Base1(){ cout<<"~Base1\n";}
};
class Base2{
public:
Base2(){ cout <<"Base2\n"; }
~Base2(){ cout <<"~Base2\n"; }
};
class Base3{
public:
Base3(){ cout <<"Base3\n"; }
~Base3(){ cout <<"~Base3\n"; }
};
class Base4{
public:
Base4(){ cout <<"Base4\n"; }
~Base4(){ cout <<"~Base4\n"; }
};
class Derived :public Base1, virtual public Base2,
public Base3, virtual public Base4//继承顺序
{
public:
Derived() :Base4(), Base3(), Base2(),Base1(), obj2(), obj1(){//初始化列表
cout <<"Derived ok.\n";
}
~Derived(){cout <<"Derived out.\n";}
protected:
OBJ1 obj1;//声明顺序
OBJ2 obj2;
};

int main()
{
Derived aa;//初始化
cout <<"This is ok.\n";
return 0;
}

输出:
Base2 //虚拟基类按照被继承顺序初始化
Base4 //虚拟基类按照被继承的顺序
Base1 //非虚拟基类按照被继承的顺序初始化
Base3 //非虚拟基类按照被继承的顺序
OBJ1 //成员函数按照声明的顺序初始化
OBJ2 //成员函数按照声明的顺序
Derived ok.
This is ok.
Derived out. //析构函数和构造函数完全相反
~OBJ2
~OBJ1
~Base3
~Base1
~Base4
~Base2