构造函数初始化列表仅用于初始化成员的值,并不指定这些初始化执行的次序。成员被初始化的次序就是定义成员的次序。第一个被定义的成员先被初始化,依次类推。一般,初始化的顺序无关紧要,然而,如果一个成员是根据其他成员而初始化,则成员的初始化顺序是至关重要的。
class x { int i;//声明顺序是先i,后j,故初始化列表中,会先初始化i,再初始化j int j; public: x(int tem): j(tem),i(j){} /*看起来是先初始化j,然后初始化i,其实恰恰相反, 先用未初始化的j来初始化i,虽然编译器不会提示你什么,但是j未初始化它便由计 算机随即分配的内存存储,它的值也是随即的,这个值可能不是你想要的,错误就 出现了。将i和j的声明顺序调过来就没有问题了。*/ };
总的来说,有虚基类时,初始化列表调用构造函数初始化的顺序如下:
1)虚基类的构造函数
2)根据派生类声明的顺序调用派生类的构造函数,对虚基类构造函数的调用被忽略
3)根据派生类对象声明的顺序调用对象所属派生类的虚基类构造函数、对象所属派生类的构造函数
无虚基类时,初始化列表调用构造函数初始化的顺序如下:
1)根据派生类声明的顺序调用对象所属派生类的基类构造函数、接着是派生类的构造函数
2)根据派生类对象声明的顺序调用对象所属派生类的基类构造函数、对象所属派生类的构造函数
你可以把我的例子运行一下,你就什么都清楚了!
#include<stdio.h> #include<stdlib.h> #include "iostream" using namespace std; class Base { public: /*Base() { cout<<"Base 构造\t"<<n<<endl; };*/ Base(int num) { n=num; cout<<"Base 构造\t"<<n<<endl; }; ~Base() { cout<<"Base 销毁\t"<<n<<endl; }; void show() { cout<<"base show"<<endl; }; protected: private: int n; }; class A:public Base { public: A(int num):Base(4) { n=num; cout<<"A 构造\t"<<n<<endl; }; ~A() { cout<<"A 销毁\t"<<n<<endl; }; void show(int y) { cout<<"A show"<<endl; }; protected: private: int n; };
#include "stdafx.h" #include "testCplus.h" //Base base2(2); //static Base base1(1); //int Base::n=9; int main() { //Base *pBase; //Base base3(3); //{ // Base base4(4); // pBase=new Base(5); // static Base base6(6); //} //delete pBase; A a1(2); A a2(3); /*Base *pb=&a; pb->show();*/ //((A *)pb)->show(0); /*Base b(6); pb=&b; pb->show();*/ return 0; }