继承和静态内存分派

发布日期:2022-08-07 13:35    点击次数:110

继承和静态内存分派

来日诰日这篇文章来聊聊继承与静态内存分派。

这内里有一个成就,当我们的基类运用静态内存分派,并且从头定义赋值和复制布局函数,这会对派生类的完成有什么影响呢?

我们来看两种环境。

派生类不消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=,从而导致一贯递归导致死循环。

 

所以我们需求手动写明浸染域剖析符,评释这是调用的父类赋值运算符,而非派生类的运算符,这一点相比隐晦,要万万留心。

 



 




Powered by 手机森林舞会游戏客户端首页 @2013-2022 RSS地图 HTML地图