服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++继承和动态内存分配

C++继承和动态内存分配

2022-09-02 13:11梁唐 C/C++

这篇文章主要介绍了C++继承和动态内存分配,当我们的基类使用动态内存分配,并且重新定义赋值和复制构造函数,这会对派生类的实现有什么影响呢?我们带罩疑问俩姐下面文章内容吧

文章转自微信 公众号:Coder梁(ID:Coder_LT)

1.简介

这里面有一个问题,当我们的基类使用动态内存分配,并且重新定义赋值和复制构造函数,这会对派生类的实现有什么影响呢?

我们来看两种情况:

2.派生类不用new

假设基类中使用了动态内存分配:

?
1
2
3
4
5
6
7
8
9
10
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

?
1
2
3
4
5
6
class lackDMA: public baseMDA {
   private:
     char color[40];
    public:
     ...
};

问题来了,我们要不要给lackDMA这个类定义析构函数、复制构造函数和赋值运算符呢?

答案是不需要。

首先是析构函数,这个很好想明白,如果我们没有定义析构函数,那么编译器会自动定义一个不执行任何操作的默认析构函数。实际上派生类的析构函数往往会在执行一些逻辑之后调用基类的构造函数,因为lackDMA类中的成员不是通过new创建的,因此不需要额外的操作,所以默认析构函数是合适的。

同样的默认复制构造函数也会执行非new创建成员的复制,所以对于color变量来说是没问题的。并且在派生类当中,默认复制构造函数除了会复制非new创建的成员之外,还会调用基类的复制构造函数来复制父类成员的部分。所以,对于派生类lackDMA来说,我们使用默认的复制构造函数一样没有问题。

赋值也是一样的,默认的赋值运算符也会自动使用基类的赋值运算符来对基类的成员进行赋值。

3.派生类使用new

我们再来看看派生类当中使用了new的情况。

?
1
2
3
4
5
6
class hasDMA: public baseMDA {
   private:
     char *style;
    public:
     ...
};

hasDMA这个类当中,我们添加了一个需要使用new创建的char*成员。在这种情况下,我们就没办法使用默认的函数了,就必须定义显式析构函数、复制构造函数和赋值运算符了,我们一个一个来看。

首先是析构函数,派生类的析构函数会自动调用基类的析构函数,所以我们只需要在析构函数当中释放派生类中独有的成员变量即可。

?
1
2
3
hasDMA::~hasDMA() {
    delete []style;
}

然后我们再来看看拷贝构造函数,由于派生类不能访问基类private成员,所以我们需要调用基类的拷贝构造函数。

?
1
2
3
4
hasDMA::hasDMA(const hasDMA& hs): baseDMA(hs) {
    style = new char[std::strlen(hs.style) + 1];
    std::strcpy(style, hs.style);
}

最后是赋值运算符,同样,由于派生类不能访问基类中私有成员,我们也需要借助基类的赋值运算符:

?
1
2
3
4
5
6
7
8
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;
}

这当中有一个语句看起来有些奇怪:

?
1
baseDMA::operator=(hs);

这是我们手动显式调用了基类的赋值运算符,我们直接用等于号赋值也有同样的效果:

?
1
*this = hs;

为什么不这么干呢?这是因为编译器在执行的时候会默认调用子类的赋值运算符hasDMA::operator=,从而导致一直递归导致死循环。

所以我们需要手动写明作用域解析符,表明这是调用的父类赋值运算符,而非派生类的运算符,这一点比较隐晦,要千万注意。

到此这篇关于C++继承和动态内存分配的文章就介绍到这了,更多相关C++继承和动态内存分配内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

延伸 · 阅读

精彩推荐
  • C/C++c语言实现的带通配符匹配算法

    c语言实现的带通配符匹配算法

    这篇文章主要介绍了c语言实现的带通配符匹配算法,需要的朋友可以参考下...

    C语言教程网13052021-02-23
  • C/C++基于Opencv实现双目摄像头拍照程序

    基于Opencv实现双目摄像头拍照程序

    这篇文章主要为大家详细介绍了基于Opencv实现双目摄像头拍照程序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    sk_sk11542021-07-28
  • C/C++C++Lambda表达式详解

    C++Lambda表达式详解

    这篇文章主要介绍了C++中的Lambda表达式详解,本文讲解了基本语法、Lambda的使用等内容,需要的朋友可以参考下,希望能够给你带来帮助...

    Yaronzz8462022-01-24
  • C/C++最短时间学会基于C++实现DFS深度优先搜索

    最短时间学会基于C++实现DFS深度优先搜索

    常见使用深度优先搜索(DFS)以及广度优先搜索(BFS)这两种搜索,今天我们就来讲讲什么是深度优先搜索,感兴趣的可以了解一下...

    ^jhao^5812021-12-21
  • C/C++C++中的四个默认成员函数与运算符重载详解

    C++中的四个默认成员函数与运算符重载详解

    这篇文章主要给大家介绍了关于C++中四个默认成员函数与运算符重载的相关资料,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需...

    Suhw4282021-05-27
  • C/C++EasyC++自动存储持续性

    EasyC++自动存储持续性

    这篇文章主要介绍了EasyC++自动存储持续性,下面文章围绕EasyC++自动存储持续性的相关资料展开全文资料,需要的小伙伴可以参考一下下面文章的具体内容...

    梁唐7512022-07-16
  • C/C++C++编程中变量的声明和定义以及预处理命令解析

    C++编程中变量的声明和定义以及预处理命令解析

    这篇文章主要介绍了C++编程中变量的声明和定义以及预处理命令解析,是C++入门学习中的基础知识,需要的朋友可以参考下...

    C++教程网6812021-03-12
  • C/C++C语言菜鸟基础教程之Hello World

    C语言菜鸟基础教程之Hello World

    C语言是一门通用计算机编程语言,应用广泛。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行...

    翡翠森林Z8542021-06-04