博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++_类继承6-继承和动态内存分配
阅读量:6093 次
发布时间:2019-06-20

本文共 2294 字,大约阅读时间需要 7 分钟。

如果基类使用动态内存分配,并重新定义赋值和复制构造函数,这将怎样影响派生类的实现?这个问题的答案取决于派生类的属性。如果派生类也使用动态内存分配,那就需要注意学习新的小技巧。

派生类不适用new

//Base Class Using DMA

class baseDMA

{

private:

       char * label;

       int rating;

      

public:

       baseDMA(const char * l ="null", int r=0);

       baseDMA(const baseDMA & rs);

       virtual ~baseDMA();

       base DMA & operator =(const baseDMA & rs);

       ...

};

 

//derived class without DMA

class lacksDMA : public baseDMA

{

private:

       char color[40];

public:

...

}

 

派生类不适用new,不需要定义显式的析构函数,因为我们假设lackDMA成员不需执行任何特殊操作,所以默认析构函数时合适的。

复制构造函数:默认复制构造函数执行成员复制,这对于动态内存分配来说是不合适的,但对于新的lacksDMA成员来说是合适的。LacksDMA类的默认复制构造函数使用显式baseDMA复制构造函数来复制lackDMA对象的baseDMA部分。因此,默认复制构造函数对于新的lackDMA成员来说是合适的,同时对于继承的baseDMA对象来说也是合适的。

对于赋值来说,也是如此。类的默认赋值运算符将自动使用基类的赋值运算符对基类组件进行赋值。因此,默认赋值运算符也是合适的。

派生类对象的这些属性也适用于本身就是对象的类成员。

派生类使用new

       这种情况下,必须为派生类定义显式析构函数,赋值构造函数和赋值运算符。

//derived class with DMA

class hasDMA:public baseDMA

{

private:

       char * style;

public:

...

}

       派生类析构函数自动调用基类的析构函数,故其自身的职责是对派生类构造函数执行工作的进行清理。因此,hasDMA析构函数必须释放指针style管理的内存,并依赖于baseDMA的析构函数来释放指针label管理的内存。

baseDMA::~baseDMA()  // takes care of baseDMA stuff

{

       delete [] label;

}

 

 

hasDMA::~hasDMA()   // takes care of hasDMA stuff

{

       delete [] style;

}

 

       接下来看复制构造函数。BaseDMA的复制构造函数遵循用于

baseDMA::baseDMA(const baseDMA & rs)

{

       label = new char[std::strlen(rs.label)+1];

       std::strcpy(label,rs.label);

       rating = rs.rating;

}

 

hasDMA复制构造函数只能访问hasDMA的数据,因此它必须调用baseDMA复制构造函数来处理共享的baseDMA数据:

hasDMA::hasDMA(const hasDMA & hs)

              :baseDMA(hs)

{

       style = new char[std::strlen(hs.style)+1];

       std::strcpy(style, hs.style);

}

 

需要注意一点是,成员初始化列表将一个hasDMA引用传递给baseDMA构造函数。

 

       接下来看赋值运算符。BaseDMA赋值运算符遵循下述常规模式:

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;

}

 

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;

 

当基类和派生类都采用动态内存分配时,派生类的析构函数,复制构造函数,赋值运算符都必须使用相应的基类方法处理基类元素。

       但这种要求是通过三种不同的方式来满足的。

       对于析构函数:这是自动完成的;

       对于构造函数:这是通过在初始化成员列表中调用基类的复制构造函数来完成的;

       对于赋值运算符,这是通过使用作用域解析运算符显式地调用基类的赋值运算符来完成的;

转载于:https://www.cnblogs.com/grooovvve/p/10422306.html

你可能感兴趣的文章
推荐几个比较好的网站
查看>>
Project Euler 45 Triangular, pentagonal, and hexagonal( 二分 + 函数指针 )
查看>>
为什么成员属性不会被重写
查看>>
SQL Server, Cannot resolve the collation conflict
查看>>
VIM技巧:选择文本块
查看>>
10分钟了解JSON Web令牌(JWT)
查看>>
Python 函数
查看>>
java低级版的分页功能:只是备忘
查看>>
102422关系
查看>>
用户 'sa' 登录失败。该用户与可信 SQL Server 连接无关联'。错误代码:18452 解决办法...
查看>>
山寨小小军团开发笔记 之 Arrow Projectile
查看>>
周鸿祎:如何成为一名优秀的产品经理?
查看>>
项目使用Entity Framework用到的公共操作方法基类(Repository)及其使用 (转载)
查看>>
《Python 学习手册4th》 第十七章 作用域
查看>>
Python爬虫学习==>第三章:Redis环境配置
查看>>
JS与AS通信-转
查看>>
JS中正则匹配开头不带空格,结尾也不带空格的字符串
查看>>
Maximal Rectangle
查看>>
windows下如何修改远程登录端口
查看>>
UVA 10603 Fill
查看>>