- 发布日期:2022-05-15 16:23 点击次数:172

今天这篇著作来聊聊罗致与动态内存分派。
这内部有一个问题,当咱们的基类使用动态内存分派,何况从头界说赋值和复制构造函数,这会对派生类的已毕存什么影响呢?
咱们来看两种情况。
派生类无须new
假定基类中使用了动态内存分派:
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); };
在这个声明里包含了构造函数、析构函数、复制构造函数和重载赋值运算符。
当今假定咱们从baseDMA派生出了类lackDMA,关联词后者不使用new:
class lackDMA: public baseMDA { private: char color[40]; public: ... };
问题来了,咱们要不要给lackDMA这个类界说析构函数、复制构造函数和赋值运算符呢?
谜底是不需要。
当先是析构函数,这个很好想显豁,如若咱们莫得界说析构函数,那么编译器会自动界说一个装假行任何操作的默许析构函数。内容上派生类的析构函数频频会在实行一些逻辑之后调用基类的构造函数,因为lackDMA类中的成员不是通过new创建的,因此不需要稀奇的操作,是以默许析构函数是相宜的。
一样的默许复制构造函数也会实行非new创建成员的复制,是以关于color变量来说是没问题的。何况在派生类当中,默许复制构造函数除了会复制非new创建的成员以外,还会调用基类的复制构造函数来复制父类成员的部分。是以,关于派生类lackDMA来说,咱们使用默许的复制构造函数一样莫得问题。
赋值亦然一样的,默许的赋值运算符也会自动使用基类的赋值运算符来对基类的成员进行赋值。
派生类使用new
咱们再来望望派生类当中使用了new的情况。
class hasDMA: public baseMDA { private: char *style; public: ... };
在hasDMA这个类当中,咱们添加了一个需要使用new创建的char*成员。在这种情况下,咱们就没见识使用默许的函数了,就必须界说显式析构函数、复制构造函数和赋值运算符了,咱们一个一个来看。
当先是析构函数,派生类的析构函数会自动调用基类的析构函数,是以咱们只需要在析构函数当中开释派生类中特有的成员变量即可。
hasDMA::~hasDMA() { delete []style; }
然后咱们再来望望拷贝构造函数,由于派生类不行造访基类private成员,是以咱们需要调用基类的拷贝构造函数。
hasDMA::hasDMA(const hasDMA& hs): baseDMA(hs) { style = new char[std::strlen(hs.style) + 1]; std::strcpy(style, hs.style); }
临了是赋值运算符,一样,由于派生类不行造访基类中私有成员,咱们也需要借助基类的赋值运算符:
hasDMA &hasDMA::operator(const hasDMA& hs) { if (this == &hs) return *this; baseDMA::operator=(hs); delete []style; style = new char[std::strlen(hs.style) + 1]; std::strcpy(style, hs.style); return *this; }
这当中有一个语句看起来有些奇怪:
baseDMA::operator=(hs);
这是咱们手动显式调用了基类的赋值运算符,咱们径直用就是号赋值也有一样的截止:
*this = hs;
为什么不这样干呢?这是因为编译器在实行的本解析默许调用子类的赋值运算符hasDMA::operator=,从而导致一直递归导致死轮回。
是以咱们需要手动写明作用域解析符,标明这是调用的父类赋值运算符,而非派生类的运算符,这少量比拟朦胧,要千万凝视。
- 最新仳离大数据曝光:“90后,还是不想受室了”2022-05-15
- 重磅!人类初次发现星河系超高能六合线源存在把柄,有望破解世纪未解之谜2022-05-15
- “福”字入钱寓吉利2022-03-24
- FOF事迹大分化 “一篮子基金”迎考试2022-03-24
- 两个奥运 相通精彩2022-03-24
- 53分6板9助2断! 一醒觉来, 杜兰特又是一场天使下凡!2022-03-21