构造函数的执行顺序
假设有如下两个类:
class Shape { public: Shape() { printf("Shape's default constructor!\n"); } // 注意char *s中的*号和s放在一起,表示定义了一个char的指针 // 因此可以同时定义成如下样子: // char ch, *s, *msg // 表示定义了一个ch字符和两个指针 Shape(char *s) { printf("Shape's constructor with msg: %s\n", s); } Shape(int a) { printf("Shape's constructor with parameter(int a).\n"); } }; class Circle : public Shape { public: Circle() { printf("Circle's default constructor!\n"); } Circle(int a) : Shape("Init Shape Directly") { printf("Circle's constrctor with parameter(int a).\n"); } };
所有子类(Circle)构造函数如果没有显式调用父类(Shape)构造函数时均会调用父类的默认构造函数。
例如:new Circle() 产生的结果是:
Shape’s default constructor!
Circle’s default constructor!
而 new Circle(1) 产生的结果是:
Shape’s constructor with msg:Init Shape Directly
Circle’s constrctor with parameter(int a).
第二种情况已经使用了某一个构造函数初始化父类,此时不再调用默认构造函数。
对数据成员的构造
如果上例中的Circle类写成下面这样:
class Circle : public Shape { private: Shape s; public: Circle() { printf("Circle's default constructor!\n"); } Circle(char *msg) : Shape(msg) { printf("Circle's default constructor!\n"); } Circle(int a) : Shape("Init Shape Directly"), s("Init a member object of Circle.") { printf("Circle's constrctor with parameter(int a).\n"); } };
此时涉及到成员对象初始化的情况,如果使用new Circle()来构造,产生的结果是:
Shape’s default constructor!
Shape’s default constructor!
Circle’s default constructor!
第一行是Circle初始化的时候调用Shape的默认构造函数产生的,之后就是Circle自己的初始化,初始化s成员对象,所以又调用了一
次Shape的默认构造函数,最后才调用Circle的初始化函数。
使用Circle的第二个构造函数能够看的更清楚一些:new Circle(“Init parent class directly!”),产生的结果是:
Shape’s constructor with msg: Init parent class directly!
Shape’s default constructor!
Circle’s default constructor!
使用Circle的第三个构造函数,就是显式的初始化成员变量s,例如:new Circle(1) 显示的结果是:
Shape’s constructor with msg:Init Shape Directly
Shape’s constructor with msg:Init a member object of Circle.
Circle’s constrctor with parameter(int a).
因此,可以看到成员对象的初始化顺序是:
初始化父类 -> 初始化子类成员 -> 调用子类构造函数体
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
其中,初始化父类的构造函数选择顺序是:
调用显式构造函数 > 调用默认构造函数
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
简单类型的数据成员的初始化
这个问题要简单得多:
class Circle { private: int r; Shape *parent; public: Circle() : r(10), parent(NULL) { } };
可见,只需要直接将需要初始化的值,放在构造函数的初始化列表当中即可。
(以上程序用GCC编译通过)