代码:
#include <iostream>
using namespace std;
class baseDMA {
private:
char* label;
int rating;
public:
baseDMA(char* l = nullptr, int r = 0);
baseDMA(baseDMA& rs) { // 复制构造函数
label = new char[strlen(rs.label) + 1];
strcpy(label, rs.label);
rating = rs.rating;
}
virtual ~baseDMA() {
delete[] label;
}; //虚析构函数。当存在派生类对象初始化基类的指针或引用,需要虚析构函数保证对象被正确释放。
baseDMA& operator=(baseDMA& rs) { // 重载赋值运算符函数
if (this == &rs) // 若是给自己赋值就直接返回
return *this;
delete[] label; // 先清空之前保存的内容
label = new char[strlen(rs.label) + 1];
strcpy(label, rs.label);
rating = rs.rating;
return *this; //返回this指针的内容
}
};
class hasDMA :public baseDMA {
private:
char* style;
public:
hasDMA(hasDMA& hs) :baseDMA(hs) {
style = new char[strlen(hs.style) + 1];
strcpy(style, hs.style);
}
hasDMA& operator=(hasDMA& hs) {
if (this == &hs) // 若是给自己赋值就直接返回
return *this;
baseDMA::operator=(hs); // 调用基类赋值运算符重载函数
delete[] style; // 先清空之前保存的内容
style = new char[strlen(hs.style) + 1];
strcpy(style, hs.style);
return *this;
}
~hasDMA() {
delete[] style;
}
};
分析:
若派生类使用了动态内存分配,那么就必须为派生类定义显示的:析构函数、复制构造函数、赋值运算符重载函数。
并且,派生类的析构函数、复制构造函数、赋值运算符重载函数都将使用相应的基类的析构函数、复制构造函数、赋值运算符重载函数来处理基类的元素。
(1)析构函数:派生类析构函数会自动调用基类的析构函数。
(2)复制构造函数:应在成员初始化列表调用基类的复制构造函数来处理基类的成员。这是合理的,因为基类的引用可以指向派生类的对象,反过来则不允许(单向性)。
(3)赋值运算符重载函数:应显示地使用作用域运算符调用基类的赋值运算符重载函数。