class A
{
public:
A( int i ){}
};
class B {
public:
B():a(1){}
//或:B( int i ):a( i ){ }。对a提供参数一定要按
//这种形式,在冒号后,不能在花括号里面!
private:
A a;
};
void main()
{
B b;
}
在B中定义 A a; 是可以通过的,但在其他地方(比如函数中)这样是不对的。 在B中定义 A a; 只是告诉编译器:“B有一个A类的对象”,并不在定义的时候创建a这个对象成员,也就不考虑它的构造函数。a这个对象成员的创建是在执行B的构造函数时进行的,B的构造函数后面必须以初始化表的形式为a对象成员提供参数,比如 B( ) : a( 1 ) { } 如果在构造函数中不为a提供参数,会发生错误。 在其他地方(比如函数中)定义A的对象时,必须定义成 A a(参数);的形式。因为定义时就要创建A的对象,所以要考虑它的构造函数。
类中定义的所有对象(包括基本类型的数据对象、无参类对象等等)的构造都是在此类的初始化列表中进行的,只不过无参和基本类型的对象被省略了。在构造函数体内的所谓初始化,只是给已经生成的对象重新赋值罢了,并没有进行对象的构造。
就是说对象构造必须在初始化列表里。这意味着其他类对象的构造先于本类的构造。
如果在类中声明的是其他类的指针,则指针初始化可以后于本类的构造。比如:
class B {
public:
B()
{
a=new A(1);
}
private:
A* a;
};
产生区别的原因是其他类对象属于类对象成员,指针不属于类对象成员。类在构造对象时,默认会先构造类对象成员(相当于在初始化类表中),在默认构造函数中会释放类对象成员的资源。而指针不属于类对象成员,不会被默认分配内存,也不会默认释放,需要手动分配内存,在析构函数中手动释放内存(自定义析构函数后,默认析构函数还是存在,而且会执行,先执行自定义的析构)。