#include <iostream>
using namespace std;
class A
{
public:
A(){cout<<"A constructor"<<endl;}
A(const A& a) {cout<<"A copy constructor"<<endl;}
};
class B
{
public:
A aa;
B(){cout<<"B constructor"<<endl;}
//B(const B& a) {cout<<"B copy constructor"<<endl;} (*)
};
int main( void )
{
B b;
B b2=b;
getchar();
return 1;
}
/*输出:不屏蔽(*)行
A constructor
B constructor
A constructor
B copy constructor
屏蔽(*)行
A constructor
B constructor
A copy constructor
*/
屏蔽(*)行时就使用了默认的拷贝构造函数,即位拷贝。既然是逐位拷贝,
那么B默认的位拷贝构造函数为什么会调用B成员A的拷贝构造函数,而不仅仅是位拷贝?
位拷贝只是在没有定义相应的构造函数或assignment运算符时才会这样进行.既然已经有了,就不会用memberwise copy了.
另外,楼主对类机制还不太熟.
B b2=b;
这里如果类B有copy ctor,则调用copy ctor,没有的话,则是 memberwise copy了.
参见于<<Effective C++ 2/e>>:
Construction of objects proceeds in two phases:
1.Initialization of data members. (See also Item 13.)
2.Execution of the body of the constructor that was called.
对象的构造分两个阶段:
1.数据成员的初始化.
2.执行构造函数体内的代码.
在你的例子中,类B有一个数据成员 A aa;
这样,就要先对aa初始化, B b2=b;也就是用b.aa来对b2.aa初始化, 可以认为是: aa(b2.aa),这就调用了类A的copy ctor了.
不屏蔽*号
B b; //调用B构造函数,又因为B有类成员A,所以先调用A的构造函数
相当于B():A(){cout<<"B constructor"<<endl;}
B b2=b; //调用B拷贝构造函数,相当于B(B&b)
B(const B& a):A() {cout<<"B copy constructor"<<endl;}
屏蔽*号:
B b; //同上
B b2=b; //B无拷贝构造函数,编译器自动生成拷贝构造函数,
1:如成员是内嵌类型,按位拷贝
2:如成员为类类型,这成员拷贝构造函数调用
因为A有拷贝构造函数,所以调用了。。。
什么时候不会发生bitwise copy?
1.当类B中含有类A的对象,而类A中定义了copy constructor时,如果你没有定义copy ctor,编译器会为你产生一个copy ctor调用类A的copy ctor;
2.当类B继承自类A,而类A中定义了copy constructor时,...;
3.当类B中有虚拟函数时,如果你没有定义copy ctor,编译器会为你产生一个copy ctor;
4.当类B虚拟继承自另一个类时,如果你没有定义copy ctor,编译器会为你产生一个copy ctor
除以上4种情况和你自己已经定义了copy ctor之外,会发生bitwise copy
所以楼主定义的类中,并不会发生bitwise copy
class A
{
public:
A(){cout<<"A constructor"<<endl;}
A(const A& a) {cout<<"A copy constructor"<<endl;}
};
class B
{
public:
A aa;
B(){cout<<"B constructor"<<endl;}
//B(const B& a) {cout<<"B copy constructor"<<endl;} (*)
};
当没有为B定义copy ctor时,因为B中含有A的对象aa, 而A中定义了copy ctor, 所以编译器会为你产生一个copy ctor, 来调用A的copy ctor, 这个copy ctor可能像这样:
B(const B &b)
{
aa=b.aa; //调用A的copy ctor
}
所以出现的结果是:
A constructor
B constructor
A copy constructor
当你为B定义了一个copy ctor后,那么编译器就假设你已经做了该做的一切,这时它就不会自作主张了,因为aa是对象成员,所以先要生成aa(如果有类中有对象成员,在给对象成员分配内存后,如果此对象有default ctor, new operator 都会调用它,上一种情况因为已经调用了A的copy ctor, 所以就不调用A的default ctor), 这时就调用aa的default ctor,然后进入B的copy ctor, 但是编译器并不会调用A的copy ctor,因为它“假设你已经做了该做的一切”.
所以出现的结果是:
A constructor
B constructor
A constructor
B copy constructor