这里假设基类已经使用了动态内存分配,所以继承与动态内存分配的关系可分两种情况来讨论。
## 派生类不使用new函数
在这种情况下不需要为派生类重新定义复制构造函数,析构函数,重载赋值运算符。派生类将使用默认复制构造函数来实现复制功能,在复制基类的成员或数据时,派生类的默认复制函数显式调用基类的复制构造函数来将基类的数据或成员复制到派生类;派生类的默认构造函数执行自身的代码后会调用基类的析构函数,所以这种情况下不为派生类重新定义析构函数是适合的;派生类的默认赋值运算符也会自动使用基类的赋值运算符来对基类的组件进行赋值。
派生类使用new函数
这种情况下要为派生类重新定义复制构造函数,析构函数,重载赋值运运算符。定义派生类复制构造函数时,由于派生类的复制构造函数只能访问本身的数据,故要调用基类的复制构造函数来复制基类的数据;定义派生类的析构函数时,只需要对派生类执行的操作进行清除即可,基类会自动调用本身的析构函数;派生类的赋值运算除了负责本身的数据外,还要负责基类的数据,这时就跟复制构造函数一样,通过使用基类的赋值运算符来实现派生类中基类部分数据的赋值。
具体的例子如下所示:
头文件:
#pragma once
#ifndef _DMA_H_
#define _DMA_H_
#include<iostream>
class baseDMA {
private:
char* label;
int rating;
public:
baseDMA(const char* l = "null", int r = 0);
baseDMA(const baseDMA& rs);
virtual ~baseDMA();
baseDMA& operator=(const baseDMA& rs);
friend std::ostream& operator<<(std::ostream& os, const baseDMA& rs);
};
class lacksDMA :public baseDMA{
private:
enum { COL_LEN = 40 };
char color[COL_LEN];
public:
lacksDMA(const char* c = "blank", const char* l = "null", int r = 0);
lacksDMA(const char* c, const baseDMA& rs);
friend std::ostream& operator<<(std::ostream& os, const lacksDMA& rs);
};
class hasDMA :public baseDMA {
private:
char* style;
public:
hasDMA(const char* s = "none", const char* l = "null", int r = 0);
hasDMA(const char* s, const baseDMA& rs);
hasDMA(const hasDMA& hs);
~hasDMA();
hasDMA& operator=(const hasDMA& rs);
friend std::ostream& operator<<(std::ostream& os, const hasDMA& rs);
};
#endif
头文件中的有关方法的定义文件如下:
#include"dma.h"
#include<cstring>
//基类baseDMA的方法
baseDMA::baseDMA(const char* l, int r) {
label = new char[std::strlen(l) + 1];
std::strcpy(label, l);
rating = r;
}
baseDMA::baseDMA(const baseDMA& rs) {
label = new char[std::strlen(rs.label) + 1];
std::strcpy(label, rs.label);
rating = rs.rating;
}
baseDMA::~baseDMA() {
delete[] label;
}
baseDMA& baseDMA::operator=(const baseDMA& rs) {
if (this == &rs)
return *this;
delete[] label;
label = new char[std::strlen(rs.label) + 1];
std::strcpy(label, rs.label);
rating = rs.rating;
return *this;
};
std::ostream& operator<<(std::ostream& os, const baseDMA& rs) {
os << "Label:" << rs.label << std::endl;
os << "Rating:" << rs.rating << std::endl;
return os;
}
//lacksDMA的方法
lacksDMA::lacksDMA(const char* c, const char* l, int r):baseDMA(l,r) {
std::strncpy(color, c, 39);
color[39] = '\0';
}
lacksDMA::lacksDMA(const char* c, const baseDMA& rs):baseDMA(rs) {
std::strncpy(color, c, COL_LEN - 1);
color[COL_LEN - 1] = '\0';
}
std::ostream& operator<<(std::ostream& os, const lacksDMA& rs) {
os << (const baseDMA&)rs;
os << "Color:" << rs.color << std::endl;
return os;
}
//hasDMA类的方法
hasDMA::hasDMA(const char* s , const char* l, int r):baseDMA(l,r) {
style = new char[std::strlen(s) + 1];
std::strcpy(style, s);
}
hasDMA::hasDMA(const char* s, const baseDMA& rs):baseDMA(rs) {
style = new char[std::strlen(s) + 1];
std::strcpy(style, s);
}
hasDMA::hasDMA(const hasDMA& hs):baseDMA(hs) {
style = new char[std::strlen(hs.style) + 1];
std::strcpy(style, hs.style);
}
hasDMA::~hasDMA() {
delete[] style;
}
hasDMA& hasDMA::operator=(const hasDMA& rs) {
if (&rs == this)
return* this;
baseDMA::operator=(rs);
delete[] style;
style = new char[std::strlen(rs.style) + 1];
std::strcpy(style, rs.style);
return *this;
}
std::ostream& operator<<(std::ostream& os, const hasDMA& rs) {
os << (const baseDMA&)rs;
os << "Style:" << rs.style << std::endl;
return os;
}
相应的测试程序文件如下:
#include<iostream>
#include"dma.h"
int main() {
using std::cout;
using std::endl;
baseDMA shirt("Portabelly", 8);
lacksDMA balloon("red", "Blimpo", 4);
hasDMA map("Mercator", "Buffalo Keys", 5);
cout << "Displaying baseDMA object:\n";
cout << shirt << endl;
cout << "Displaying lacksDMA object:\n";
cout << balloon << endl;
cout << "DIsplaying hasDMA object:\n";
cout << map << endl;
lacksDMA balloon2(balloon);
cout << "Result of lacksDMA copy:\n";
cout << balloon2 << endl;
hasDMA map2;
map2 = map;
cout << "Result of hasDMA assignment:\n";
cout << map2 << endl;
return 0;
}
注意:若要在vs中运行该程序,这要修改该项目的属性,在c/c++预处理器定义中加入_CRT_SECURE_NO_WARNINGS。
参考文献:c++ primer plus