下面我的程序其实本质上就是模拟了默认的派生类复制构造函数和默认的派生类赋值运算符函数的实现。
#include<iostream>
using namespace std;
class B {
private:
int b;
public:
B(int bb = 0) :b(bb) {}
B(const B&obj) :b(obj.b) {}
B& operator=(const B&obj) {
if (this == &obj)
return *this;
this->b = obj.b;
return *this;
}
};
class D :public B {
private:
int d;
public:
D(int bb, int dd) :B(bb), d(dd) {}
//派生类的复构函数
D(const D&obj) :B(obj) {//调用基类的复构函数(用到了派生类对象转换为基类对象使用)
this->d = obj.d;
}
//派生类的赋值操作符函数
D& operator=(const D&obj) {
if (this == &obj)
return *this;
this->B::operator=(obj);
this->d = obj.d;
}
};
int main() {
B b(1);
D d1(1, 2);
D d2(d1);//调用派生类的复构函数
D d3(6, 8);
d2 = d3;//调用派生类的赋值运算符函数
system("pause");
return 0;
}
在派生类的复制构造函数中,首先调用基类的复制构造函数复制基类的数据成员(注意传参用到了派生类对象转换为基类对象使用),然后再复制派生类新增的数据成员。
在派生类的赋值运算符函数中,同样首先调用基类的赋值运算符函数对基类的数据成员赋值(注意传参用到了派生类对象转换为基类对象使用),然后再给派生类新增的数据成员赋值。
对程序稍作修改(我先删掉了派生类中的赋值运算符函数,又把基类的赋值运算符函数改了,使其丧失赋值功能):
#include<iostream>
using namespace std;
class B {
private:
int b;
public:
B(int bb = 0) :b(bb) {}
B(const B&obj) :b(obj.b) {}
B& operator=(const B&obj)//修改基类的赋值运算符函数使其丧失功能
{
return *this;
}
};
class D :public B {
private:
int d;
public:
D(int bb, int dd) :B(bb), d(dd) {}
//派生类的复构函数
D(const D&obj) :B(obj) {//调用基类的复构函数(用到了派生类对象转换为基类对象使用)
this->d = obj.d;
}
};
int main() {
B b(1);
D d1(1, 2);
D d2(d1);//调用派生类的复构函数
D d3(6, 8);
d2 = d3;//调用派生类的默认的赋值运算符函数
system("pause");
return 0;
}
d2的结果如下:
分析:因为此时派生类没有赋值运算符函数,所以执行d2 = d3;
时系统会自动调用派生类默认的赋值运算符函数,在派生类默认的赋值运算符函数中,又会先调用基类的赋值运算符函数(又因为我已经使其丧失了功能),最后再给派生类新增的数据成员赋值。所以最终得到的结果如上。