C++学习笔记10-继承和动态内存分配,易错点总结

动态内存分配:

①派生类不使用new

Q:是否需要为派生类重新定义复制构造函数,复制运算符,析构函数?
A:不需要,子类中默认的复制构造函数,复制赋值运算符,析构函数就能完成所有的工作,虽然是浅层
复制,但是由于子类中没有申请动态内存,子类默认的复制构造函数,复制赋值运算符,析构函数都将
自动调用父类的复制构造函数,复制赋值运算符,析构函数,而父类的这些成员都是深复制的即可

②派生类使用new

Q:是否需要为派生类重新定义复制构造函数,复制运算符,析构函数?
A:需要!!

(Ⅰ)如何定义派生类复制构造函数

初始化列表显式调用基类的复制构造函数,并执行派生类新增数据的深度复制

Base::Base(const Base & o)
{
	str = new char[std::strlen(o.str)+1];
	std::strcpy(str,o.str);
}
Sub::Sub(const Sub & o) : Base(o)//显式调用基类的复制构造函数
{	下面是派生类成员的深度复制
	sub_str = new char[std::strlen(o.sub_str)+1];
	std::strcpy(sub_str,o.sub_str);
}

假设sub_str是派生类的新增的指针成员,str是基类的指针成员,子类的复制构造函数显式调用父类的
复制构造函数,对派生类的成员执行深度复制
即可

(Ⅱ)如何定义派生类复制赋值运算符

Base & Base::operator=(const Base & o)
{
	if(this!=&o)
	{
		delete[] str;
		str = new char[std::strlen(o.str)+1];
		std::strcpy(str,o.str);
	}
	return *this;
}
Sub & Sub::operator=(const Sub & o)
{
	if(this==&o)
	{
		delete[] sub_str;
		/*#1*/Base::operator=(o);显式使用基类的复制赋值运算符,完成基类成员的深度复制,*this是隐藏调用者
		/*#2*/或者这样this->Base::operator=(o);
		/*#3*/*this = o;绝对不能这样做,因为隐式调用了子类的复制赋值运算符,无限递归!!!
		sub_str = new char[std::strlen(o.sub_str)+1];
		std::strcpy(sub_str,o.sub_str);
	}
	return *this;
}

#1和#2选其一就行,绝对不能选#3的代码

(Ⅲ)如何定义派生类析构函数

在析构函数里面delete派生类里面的动态内存即可,然后派生类的析构函数会自动调用基类的析构函数
,一般来说,基类的析构函数只要也有delete基类的动态内存,就没有任何问题了
但是要注意:和构造函数的调用顺序不同,析构函数是先调用派生类的,再调用基类的析构函数!!

Base::~Base()
{
	delete[] str;
}
Sub::~Sub()
{
	delete[] sub_str;
	隐式执行基类析构函数
}

猜你喜欢

转载自blog.csdn.net/weixin_46028606/article/details/107549077
今日推荐