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

派生类不适用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. codeforce468DIV2——E. Game with String

    题目 Vasya and Kolya play a game with a string, using the following rules. Initially, Kolya creates a ...

  2. Linux常用基本命令 1

    useradd 创建用户. password 修改密码. date 查看时间 man date 帮助文档.f往后翻 b往前翻 q退出.软修改 man hwclock 修改硬件时钟, cal 查看日历 ...

  3. IDEA maven打包时跳过测试

    配置这个install -Dmaven.test.skip=true, 可以跳过business项目本地启动自动跑测试用例

  4. Docker学习笔记_安装和使用Python

    一.实验目标 在Docker里安装Python3.5 二.准备 1.宿主机OS:Win10 64 2.虚拟机OS:Ubuntu18.04 3.操作账号:Docker 二.安装过程 1.搜索Python ...

  5. Tarjan算法求出强连通分量(包含若干个节点)

    [功能] Tarjan算法的用途之一是,求一个有向图G=(V,E)里极大强连通分量.强连通分量是指有向图G里顶点间能互相到达的子图.而如果一个强连通分量已经没有被其它强通分量完全包含的话,那么这个强连 ...

  6. IE浏览器和Firefox浏览器兼容性问题及解决办法

    IE浏览器和Firefox浏览器兼容性问题及解决办法 为了方便大家阅读代码,以下以 IE 代替 Internet Explorer,以 MF/FF 代替 Mozzila Firefox : 1.//w ...

  7. ASP.NET多页面传递数据,附框架源码

    很多时候我们需要把数据传递到多个页面,比如表单提交可以指定提交数据到某个页面,那么关闭某个页面怎么把数据传递到上一个页面或者它的父页面. 在这里我附一段源码用于当前页面关闭指定某个页面刷新. 子页面方 ...

  8. 自定义UINavigationBar的背景【转】

    from:http://cocoa.venj.me/blog/custom-navbar-background/ 为了让我们的应用程序更加美观,我们往往希望对iPhone自带的控件进行一点自定义.比如 ...

  9. 团队项目第六周-Alpha阶段项目复审(深海划水队)

    经小组讨论后得出以下排名: 队名 优点 缺点 排名 大猪蹄子队 界面优美,功能简洁易懂,单词解释较为完善 互动方式.操作简易性有待优化,有部分功能尚未完成 1 Running Duck队 基本功能已经 ...

  10. angular 守卫路由

    import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; im ...