构造函数与虚析构函数

2024-03-07 19:48

本文主要是介绍构造函数与虚析构函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 构造函数
         因为在派生类中构造函数是不能继承的,也没有重定义的必要。在构造函数中调用虚函数将破坏动态绑定逻辑。下面的例子说明了这样动态绑定逻辑。
例:       
  #include<iostream.h>
  class base
   {
      protected:
      int x;
      public:
      base (int m)
       {
         x=m+1;
         print( );
       }
      virtual void print( )
       {
         cout<<”The virtual function  in base is called!”<<endl;
        cout<<x<<endl;
    }
};
class derive: public base
  {
     private:
     int y;
     public:
    derive (int m): base(m)
      {
        y=m;
        print( );
      }
virtual void print( )
    {
      cout<<”The virtual function in derive is called!”<<endl;
      cout<<y<<endl;
    }
 };
 void main( )
    {
      derive  obj(10);
    }
程序的输出结果为:
         The virtual function in base is called!
         11
         The virtual function in derive is called!
         10
         程序从创建派生类的对象开始执行,在执行中,先要调用基类的构造函数。此时派生类的创建过程尚未完成,只能按静态绑定调用基类的虚函数,无法实现预期的多态逻辑。
请记住:
          在构造和析构期间不要调用virtual 函数,因为这类调用从不下降至derived class(比起当前执行构造函数和析构函数的那层)。       
        如果在构造函数或析构函数中调用虚函数,则运行的是为构造函数或析构函数自身类型定义的版本。可以理解为:在base class 构造期间, virtual 函数不是virtual 函数。

2.虚析构函数

析构函数可以通过virtual修饰而声明为虚析构函数。虚析构函数与一般虚函数的不同之处在于:
(1)覆盖虚析构函数的重定义函数就是派生类的析构函数,不要求同名;
(2)虚析构函数由系统自动调用;
(3)一个虚析构函数的版本被调用后,接着就要调用被它覆盖的基类版本,依次类推,直到调用了派生序列的根类的析构函数版本为止。
     

    为什么析构函数为虚?

     在处理继承层次中的对象时,指针的静态类型可能与被删除对象的动态类型不同。因此基类中的析构函数必须为虚函数(虚函数特性会被继承,派生类的析构函数也是虚的)。

Base *pBase = new Derived;

delete pBase;

如果Base的析构函数不为虚,删除指针时只会执行Base的析构函数,造成内存泄漏;反之,则先析构Derived,再析构Base。

例:

#include<iostream.h>
 class base
  {
    public:
    virtual void say( )
     {
       cout<<”I am base.”<<endl;
     }
    ~base( )
     {
       cout<<”Delete object of
              base”<<endl;
     }
  };
class derived:public base
 {
   public:
   virtual void say( )
    {
      cout<<”I am derived”<<endl;
    }
  ~derived( )
    {
      cout<<”Delete object of derived”<<endl;
    };
void main( )
  {
    base *p1=new derived;
    p1->say( );
    delete p1;
  }
程序的输出结果为:
         I am derived
         Delete object of derived
        显然,p1->say( )语句正确地动态绑定了派生类中的重载代码,delete p1语句也正确地释放了为p1分配的内存空间。 但是,base*p1=new derived 语句执行时,先创建了一个指向base类对象的指针p1,然后又创建了一个derived类的动态对象,最后再让p1指向derived的对象。所以delete p1执行时应调用base和derived两个类的构造函数。
        由于该程序定义的多态性中没有将析构函数用virtual关键字说明, delete p1的执行是不正确的。 析构函数加上virtual 关键字说明,重新运行程序将得到以下正确结果:
         I am derived
         Delete object of derived
         Delete object of base

请记住:
• polymorphic (带多态性质的) base classes 应该声明一个virtual 析构函数。如果class 带有任何virtual 函数,它就应该拥有一个virtual 析构函数。
• Classes 的设计目的如果不是作为base classes 使用,或不是为了具备多态性(polymorphically) ,就不该声明virtual 析构函数。

这篇关于构造函数与虚析构函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/784622

相关文章

Pandas中统计汇总可视化函数plot()的使用

《Pandas中统计汇总可视化函数plot()的使用》Pandas提供了许多强大的数据处理和分析功能,其中plot()函数就是其可视化功能的一个重要组成部分,本文主要介绍了Pandas中统计汇总可视化... 目录一、plot()函数简介二、plot()函数的基本用法三、plot()函数的参数详解四、使用pl

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指

Python正则表达式语法及re模块中的常用函数详解

《Python正则表达式语法及re模块中的常用函数详解》这篇文章主要给大家介绍了关于Python正则表达式语法及re模块中常用函数的相关资料,正则表达式是一种强大的字符串处理工具,可以用于匹配、切分、... 目录概念、作用和步骤语法re模块中的常用函数总结 概念、作用和步骤概念: 本身也是一个字符串,其中

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

MySQL中FIND_IN_SET函数与INSTR函数用法解析

《MySQL中FIND_IN_SET函数与INSTR函数用法解析》:本文主要介绍MySQL中FIND_IN_SET函数与INSTR函数用法解析,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一... 目录一、功能定义与语法1、FIND_IN_SET函数2、INSTR函数二、本质区别对比三、实际场景案例分

C++ Sort函数使用场景分析

《C++Sort函数使用场景分析》sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变,如果某些场景需要保持相同元素间的相对顺序,可使... 目录C++ Sort函数详解一、sort函数调用的两种方式二、sort函数使用场景三、sort函数排序

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

C/C++错误信息处理的常见方法及函数

《C/C++错误信息处理的常见方法及函数》C/C++是两种广泛使用的编程语言,特别是在系统编程、嵌入式开发以及高性能计算领域,:本文主要介绍C/C++错误信息处理的常见方法及函数,文中通过代码介绍... 目录前言1. errno 和 perror()示例:2. strerror()示例:3. perror(

Kotlin 作用域函数apply、let、run、with、also使用指南

《Kotlin作用域函数apply、let、run、with、also使用指南》在Kotlin开发中,作用域函数(ScopeFunctions)是一组能让代码更简洁、更函数式的高阶函数,本文将... 目录一、引言:为什么需要作用域函数?二、作用域函China编程数详解1. apply:对象配置的 “流式构建器”最