1.拷贝构造函数调用的时机:
用已有对象初始化新的对象,调用拷贝构造;
调用函数时,实参对象按值传递给相应的形参对象时,调用拷贝构造;
把对象作为返回值,会产生一个临时无名对象,调用拷贝构造。
ps:赋值不会调用拷贝构造函数
2.继承关系中的拷贝构造函数
隐含的:自动调用基类的
显式声明的:一般需要为基类相应的拷贝构造函数传递参数。一般是用派生类的对象初始化基类的引用。
3.将派生对象赋值给基类对象
赋值的本质是将现有的数据写入已分配好的内存中,对象的内存只包含了成员变量,所以对象之间的赋值是成员变量的赋值,成员函数不存在赋值问题。
也就是说,基类 基类对象 = 派生类对象,但 基类.func() 始终调用的是基类自己的func(这跟那个多态没关系,不要混,多态是基类指针指向派生类对象,然后虚函数实现多态)
#include <iostream>
using namespace std;
class AA {
public:
AA() {
cout << "constructor aa" << endl;
}
AA(AA& a) {
cout << "copyConstructor aa" << endl;
}
~AA() {
cout << "destructor aa" << endl;
}
virtual void fun() {
cout << "aa::fun() called" << endl;
}
};
class BB :public AA {
public:
BB() {
cout << "constructor bb" << endl;
}
BB(BB& b) :AA(b) { //为派生类编写拷贝构造函数,一般要为基类相应的拷贝构造函数传参。且一般是用派生类对象初始化基类的引用
cout << "copyConstructor bb" << endl;
}
~BB() {
cout << "destructor bb" << endl;
}
void fun() {
cout << "bb::fun() called" << endl;
}
};
BB Call1(BB b) { //调用函数时,实参对象按值传递给相应的形参对象时,拷贝构造——派生类调基类的拷贝构造
cout << endl;
cout << "call1……" << endl;
b.fun();
return b; //把对象作为返回值,会产生一个临时无名对象,调用拷贝构造。然后临时无名对象析构,参b析构
}
void Call2(AA a) { //派生类对象赋值给基类对象(同步骤2)
cout << endl;
cout << "call2……" << endl;
a.fun();
}
int main() {
cout << "……1……" << endl;
BB b;
cout << endl;
cout << "……2……" << endl;
AA a = b; //派生类对象赋值给基类对象(用已有对象初始化新的对象)
//调用的是a的拷贝构造,因为只是成员变量赋值,不影响成员函数,也不影响this指针。
a.fun(); //所以这里还有call2中的,a虽然是用派生类对象赋值的,但调用的仍然是a的fun()
//ps:派生类对象赋值给基类对象时,会舍弃派生类新增的成员,也就是“大材小用”
cout << endl;
cout << "……3……" << endl;
Call1(b);
cout << endl;
cout << "……4……" << endl;
Call2(b);
//AA a,aa;
//AA aaa = a; //用已有对象初始化新的对象,调用拷贝构造
//aa = a; //赋值不会调用拷贝构造函数
cout << endl;
cout << "……over……" << endl;
return 0;
}