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

派生类不适用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;

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

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

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

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

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

C++_类继承6-继承和动态内存分配的更多相关文章

  1. C++之继承和动态内存分配

    C++之继承和动态内存分配         如果基类使用动态内存分配,并重新定义赋值和复制构造函数,这将如何影响派生类的实现呢?这取决于派生类的属性,如果派生类也使用动态内存分配,这将如何实现呢?这种 ...

  2. C++解析(25):关于动态内存分配、虚函数和继承中强制类型转换的疑问

    0.目录 1.动态内存分配 1.1 new和malloc的区别 1.2 delete和free的区别 2.虚函数 2.1 构造函数与析构函数是否可以成为虚函数? 2.2 构造函数与析构函数是否可以发生 ...

  3. C++_类和动态内存分配3-构造函数中使用new的注意事项

    如果在构造函数中使用new来初始化对象的指针成员时必须特别小心. 1 如果在构造函数中使用new来初始化指针成员,则应在析构函数中使用delete. 2 new和delete必须相互兼容.new对应于 ...

  4. String类型_static成员_动态内存分配_拷贝构造函数_const关键字_友元函数与友元类

    1:String类型 #include <iostream> using namespace std; int main() { //初始化方法 string s1 = "hel ...

  5. 《C++ Primer Plus》读书笔记之十—类和动态内存分配

    第12章 类和动态内存分配 1.不能在类声明中初始化静态成员变量,这是因为声明描述了如何分配内存,但并不分配内存.可以在类声明之外使用单独的语句进行初始化,这是因为静态类成员是单独存储的,而不是对象的 ...

  6. C++ primer plus读书笔记——第12章 类和动态内存分配

    第12章 类和动态内存分配 1. 静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域运算符来指出静态成员所属的类.但如果静态成员是整形或枚举型const,则可以在类声明中初始化 ...

  7. C++学习笔记(十一):void*指针、类型转换和动态内存分配

    void*指针 void关键字表示“空类型”的概念.但是,这里的“空类型”不表示“任意类型”,而是表示不存在的意思,也就是说C/C++不允许你写语句void a,不存在类型为void的东西. void ...

  8. Java静态内存与动态内存分配的解析

    1. 静态内存 静态内存是指在程序开始运行时由编译器分配的内存,它的分配是在程序开始编译时完成的,不占用CPU资源. 程序中的各种变量,在编译时系统已经为其分配了所需的内存空间,当该变量在作用域内使用 ...

  9. C++指针和动态内存分配

    指针和动态内存分配 数组与指针 数组 数组名是一个指针常量. 数组名传递数据时,传递的是地址. 数组作为函数参数时不指定第一维大小. 对象数组 A a[2] = {A(1,2)}; 执行时先调用有参数 ...

随机推荐

  1. memcache 随笔

    第一次用可能有很多不足的地方  以后慢慢改进. memcache  是一个简单的键/值对    是通过键和值储存信息到memcache中 ,通过特定的键请求来返回信息. 信息会无限期的保留在内存中 : ...

  2. css 样式文字溢出显示省略号

    在table中使用溢出样式,table样式要设置为”table-layout: fixed“,即<table style="table-layout: fixed;"> ...

  3. ROS源码解读(一)--局部路径规划

    博客转载自:https://blog.csdn.net/xmy306538517/article/details/78772066 ROS局部路径导航包括Trajectory Rollout 和 Dy ...

  4. 专题2-通过按键玩中断\2440按键中断编程lesson2

    1.程序优化 修改Makefile 把main.c里面的mmu代码复制到mmu.c并修改如下 main.c的修改 由于在bootloader当中一般不会使用MMU,所以 main.c 加入led.c文 ...

  5. Linux网络编程IPv4和IPv6的inet_addr、inet_aton、inet_pton等函数小结(转)

    原文:http://blog.csdn.net/ithomer/article/details/6100734 知识背景: 210.25.132.181属于IP地址的ASCII表示法,也就是字符串形式 ...

  6. Python htmlTestRunner生成测试报告Demo

    #该代码段是ReadTxt_demo.py 的代码,用户读取txt 文件中的用户信息. #ReadTxt_demo.py def readTxt(filePath): fo = open(filePa ...

  7. DELPHI 调用系统 ADO 配置窗体 提高软件易用性

    最近DELPHI好像不太景气哦,把自己的代码拿出来晒晒.高手别喷哦. 直接上代码 implementation uses AdoConEd; var  saveconnstr:string; proc ...

  8. 我用Django搭网站(3)-表单RSA加密

    之前开发项目时因为种种原因一直使用明文提交,表单直接明文提交非常不安全,只要稍加操作就能轻易获取用户的信息.在众里寻他千百度之后决定使用RSA加密方式,简单可靠. 项目准备 一.安装PyCrypto库 ...

  9. PHP 去掉emoji字符

    function isMatchEmoji($str) { $pattern='/./u'; $rs=preg_match_all($pattern,$str,$match); if($rs>0 ...

  10. Sharepoint2013搜索学习笔记之自定义结果精简分类(八)

    搜索结果页左边的结果精简分类是可以根据搜索结果自定义的,在搜索的部门日志结果集页面上我搜索测试关键字,左边分类导航在默认分类的基础上增加了一个日志类型的分类,如下图: 要实现这个效果,导航到之前定义的 ...