一般来说,类中的数据成员是私有的,不能通过对象共有访问的方式对数据成员赋初始值。一般来说,构造函数就是用来用来在创建对象时初始化对象, 为对象数据成员赋初始值。
构造函数是类的一种特殊成员函数,不需要人为调用,而是在建立对象时自动被执行。
赋值初始化,通过在函数体内进行赋值初始化;
列表初始化,在冒号后使用初始化列表进行初始化。
这两种方式的主要区别在于:
对于在函数体中初始化,是在所有的数据成员被分配内存空间后才进行的。
列表初始化是给数据成员分配内存空间时就进行初始化,
就是说分配一个数据成员只要冒号后有此数据成员的赋值表达式(此表达式必须是括号赋值表达式),
那么分配了内存空间后在进入函数体之前给数据成员赋值,
就是说初始化这个数据成员此时函数体还未执行。
列表初始化:
#include
using namespace std;
class solution {
public:
solution(int value1,int value2):a(value1),b(value2){}//列表初始化
void print() {
cout << "a=" << a << " " << "b=" << b << endl;
}
private:
int a;
int b;
};
int main()
{
solution s(1, 2);
s.print();
return 0;
}
赋值初始化:
#include
using namespace std;
class solution {
public:
solution(int value1,int value2){
a = value1;
b = value2;
}//列表初始化
void print() {
cout << "a=" << a << " " << "b=" << b << endl;
}
private:
int a;
int b;
};
int main()
{
solution s(1, 2);
s.print();
return 0;
}
a=1 b=2
必须使用成员初始化的四种情况:
当初始化一个引用成员时;
当初始化一个常量成员时;
当调用一个基类的构造函数,而它拥有一组参数时;
当调用一个成员类的构造函数,而它拥有一组参数时;
#include
using namespace std;
class solution {
public:
solution(int& value1,int value2):a(value1),b(value2){
}//正确,列表初始化
/*solution(int& value1, int value2) {
a = value1;
b = value2;
}//错误,赋值初始化*/
void print() {
cout << "a=" << a << " " << "b=" << b << endl;
}
private:
int& a;
int b;
};
int main()
{
int a = 1;
solution s(a, 2);
s.print();
return 0;
}
赋值初始化是在构造函数当中做赋值的操作,而列表初始化是做纯粹的初始化操作。我们都知道,C++的赋值操作是会产生临时对象的。临时对象的出现会降低程序的效率。
虚拟基类的构造函数(多个虚拟基类则按照继承的顺序执行构造函数)。
基类的构造函数(多个普通基类也按照继承的顺序执行构造函数)。
类类型的成员对象的构造函数(按照初始化顺序)
派生类自己的构造函数。
#include
using namespace std;
//虚基类
class A {
public:
A(int value) :a(value) {
cout << "A的初始化" << endl;
}
private:
int a;
};
//基类
class B {
public:
B(int value) :b(value) {
cout << "B的初始化" << endl;
}
private:
int b;
};
//类类型的成员
class C {
public:
C() {
cout << "C的初始化" << endl;
}
};
//派生类
class D:public B,virtual public A {
public:
D(int value1, int value2) :B(value1), A(value2) {//初始化顺序和初始化列表的顺序无关,构造函数的初始化顺序按照一定规则进行。
cout << "D的初始化" << endl;
}
private:
C c;
};
int main()
{
D d(1, 2);
return 0;
}
A的初始化
B的初始化
C的初始化
D的初始化