构造函数不能声明为虚函数,析构函数可以声明为虚函数,而且有时是必须声明为虚函数。

不建议在构造函数和析构函数里面调用虚函数。

构造函数不能声明为虚函数的原因是:

解释一:所谓虚函数就是多态情况下只执行一个。而从继承的概念来讲,总是要先构造父类对象,然后才能是子类对象。如果构造函数设为虚函数,那么当你在构造父类的构造函数时就不得不显示的调用构造。还有一个原因就是为了防错,试想如果你在子类中一不小心重写了个跟父类构造函数一样的函数,那么你的父类的构造函数将被覆盖,也即不能完成父类的构造.就会出错。

解释二:虚函数的主要意义在于被派生类继承从而产生多态。派生类的构造函数中,编译器会加入构造基类的代码,如果基类的构造函数用到参数,则派生类在其构造函数的初始化列表中必须为基类给出参数,就是这个原因。

虚函数的意思就是开启动态绑定,程序会根据对象的动态类型来选择要调用的方法。然而在构造函数运行的时候,这个对象的动态类型还不完整,没有办法确定它到底是什么类型,故构造函数不能动态绑定。(动态绑定是根据对象的动态类型而不是函数名,在调用构造函数之前,这个对象根本就不存在,它怎么动态绑定?)

编译器在调用基类的构造函数的时候并不知道你要构造的是一个基类的对象还是一个派生类的对象。

析构函数设为虚函数的作用:

解释:在类的继承中,如果有基类指针指向派生类,那么用基类指针delete时,如果不定义成虚函数,派生类中派生的那部分无法析构。

#include   "stdafx.h"
#include   "stdio.h"   class   A
{   public:   A();   virtual   ~A();
};   A::A()
{   }   A::~A()
{   printf("Delete   class   AP/n");
}   class   B   :   public   A
{   public:   B();   ~B();
};   B::B()
{  }   B::~B()
{   printf("Delete   class   BP/n");
}   int   main(int   argc,   char*   argv[])
{   A   *b=new   B;   delete   b;   return   0;
}       

输出结果为:Delete   class   B

Delete   class   A

如果把A的virtual去掉:那就变成了Delete   class   A

因此在类的继承体系中,基类的析构函数不声明为虚函数容易造成内存泄漏。所以如果你设计一定类可能是基类的话,必须要声明其为虚函数。正如Symbian中的CBase一样。Note:

1. 如果我们定义了一个构造函数,编译器就不会再为我们生成默认构造函数了。

2. 编译器生成的析构函数是非虚的,除非是一个子类,其父类有个虚析构,此时的函数虚特性来自父类。

3. 有虚函数的类,几乎可以确定要有个虚析构函数。

4. 如果一个类不可能是基类就不要申明析构函数为虚函数,虚函数是要耗费空间的。

5. 析构函数的异常退出会导致析构不完全,从而有内存泄露的问题。最好是提供一个管理类,在管理类中提供一个方法来析构,调用者再根据这个方法的结果决定下一步的操作。

6. 在构造函数不要调用虚函数。在基类构造的时候,虚函数是非虚,不会走到派生类中,既是采用的静态绑定。显然的是:当我们构造一个子类的对象时,先调用基类的构造函数,构造子类中基类部分,子类还没有构造,还没有初始化,如果在基类的构造中调用虚函数,如果可以的话就是调用一个还没有被初始化的对象,那是很危险的,所以C++中是不可以在构造父类对象部分的时候调用子类的虚函数实现。但是不是说你不可以那么写程序,你这么写,编译器也不会报错。只是你如果这么写的话编译器不会给你调用子类的实现,而是还是调用基类的实现。

7. 在析构函数中也不要调用虚函数。在析构的时候会首先调用子类的析构函数,析构掉对象中的子类部分,然后在调用基类的析构函数析构基类部分,如果在基类的析构函数里面调用虚函数,会导致其调用已经析构了的子类对象里面的函数,这是非常危险的。

8. 记得在写派生类的拷贝函数时,调用基类的拷贝函数拷贝基类的部分,不能忘记了。

如果一个类是作为基类使用,那么他的虚构函数一定要是虚的,即用virtual关键字(参数为零则为纯虚函数).   否则会有内存泄漏(很重要),因为当用基类的指针删除一个派生类的对象时,要调用派生类的析构函数.但是   其子类或者子子类可以的析构函数可以是虚函数,也可以不是虚函数.(不加virtual 关键字则不会调用派生   类的析构函数,而上面用了ClxBase *pTest = new ClxDerived;语句也就是new的ClxDerived对象没有   销毁,所以产生内存泄漏) 2.类中的虚函数,如果一个类中的函数被声明成为虚函数,那么其子类不用在声明为虚函数(当子类还有子类时),   也可以声明为虚函数.结果是一样的.同虚析构函数的道理是一样的.当然,并不是要把所有类的析构函数都写   成虚函数。因为当类里面有虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就   会增加类的存储空间。所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数。

具体例子:

#include "iostream.h"class ClxBase
{public:ClxBase() {};virtual ~ClxBase() { cout << "Output from the destructor of class ClxBase!" << endl; };virtual void DoSomething() { cout << "Do something in class     ClxBase!"<< endl; };
};class ClxDerived : public ClxBase
{public:ClxDerived() {};virtual~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };//此处的virtual可以去掉virtual void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };//此处的virtual可以去掉
};class ClxThrived : public ClxDerived
{
public:ClxThrived(){};virtual ~ClxThrived(){cout << "Output from the destructor of class ClxThrived!" << endl;};//此处的virtual可以去掉virtual void DoSomething(){cout << "Do something in class ClxThrived!" << endl;}//此处的virtual可以去掉
};
void main()
{ClxBase *pTest1 = new ClxBase;pTest1->DoSomething();delete pTest1;//1
 ClxBase *pTest2 = new ClxDerived;pTest2->DoSomething();delete pTest2;//2 用基类的指针删除一个派生类的对象时
 ClxDerived *pTest3 = new ClxDerived;pTest3->DoSomething();delete pTest3;//3
 ClxBase *pTest4 = new ClxThrived;pTest4->DoSomething();delete pTest4;//4 用基类的指针删除一个派生类的对象时
 ClxDerived *pTest5 = new ClxThrived;pTest5->DoSomething();delete pTest5;//5 用基类的指针删除一个派生类的对象时
 ClxThrived *pTest6 = new ClxThrived;pTest6->DoSomething();delete pTest6;//6
}

转载于:https://www.cnblogs.com/followyourdream/p/3397387.html

构造函数和析构函数能否声明为虚函数?相关推荐

  1. 构造函数不可以声明为虚函数,析构函数可以声明为虚函数

    构造函数不能声明为虚函数,而析构函数可以声明为虚函数,在有的情景下析构函数必须声明为虚函数.  不建议在构造函数和析构函数里调用虚函数. 构造函数不能声明为虚函数的原因? 构造一个对象时,必须知道对象 ...

  2. 【C++深度剖析教程33】C++中的构造函数与析构函数是否可以为虚函数

    加qq1126137994 微信:liu1126137994 一起学习更多技术!!! 问题一:构造函数与析构函数可以成为虚函数么? 答案: 1.构造函数不可以成为虚函数 因为在构造函数执行结束后,虚函 ...

  3. C++经验(四)-- 基类构造函数和析构函数中调用virtual虚函数?

    class Base {public:Base();virtual void oneFunction() = 0;... };Base::Base() {...oneFunction(); }clas ...

  4. 为什么基类的析构函数要声明成虚函数

    记得以后基类(父类) 的析构函数最好是声明为 虚函数 即:virtual 开发中遇到了一个比较傻逼的bug,也证明了理论与实际之间的差距. 在基类中没有声明其析构函数为虚函数,导致delete 释放操 ...

  5. 构造函数和析构函数能不能是虚函数

    从实现上看,vbtl在构造函数调用后才建立,因而构造函数不可能成为虚函数      从实际含义上看,在调用构造函数时还不能确定对象的真实类型(因为子类会调父类的构造函数):而且构造函数的作用是提供初始 ...

  6. 为什么析构函数可以能声明为虚函数,构造函数不可以

    转自:http://blog.csdn.NET/chen825919148/article/details/8020550 构造函数不能声明为虚函数,析构函数可以声明为虚函数,而且有时是必须声明为虚函 ...

  7. 基类的析构函数不能被继承。_为什么要把C++类中的析构函数声明为虚函数?

    如题,当一个类为基类的时候,通常其析构函数被声明为虚函数,这是为啥? class BaseCls { public: BaseCls() { printf("BaseCls()n" ...

  8. 构造函数为什么一般不定义为虚函数?而析构函数一般写成虚函数的原因 ?

    1.构造函数不能声明为虚函数 1)因为创建一个对象时需要确定对象的类型,而虚函数是在运行时确定其类型的.而在构造一个对象时,由于对象还未创建成功,编译器无法知道对象的实际类型,是类本身还是类的派生类等 ...

  9. C++中不能声明为虚函数的有哪些函数

    常见的不不能声明为虚函数的有:普通函数(非成员函数):静态成员函数:内联成员函数:构造函数:友元函数. 1.为什么C++不支持普通函数为虚函数? 普通函数(非成员函数)只能被overload,不能被o ...

最新文章

  1. 操作系统期末复习重点题型归纳
  2. 大数据基础设施建设需要得到重视 | 记清华大数据“应用·创新”讲座
  3. Spring Data JPA例子[基于Spring Boot、Mysql]
  4. Java 技术篇 - java同时连接多种数据库执行sql语句的兼容性验证,数据库类型包括:oracle、sqlserver、DB2、人大金仓、达梦、PG、瀚高、polardb
  5. 什么时候该用MySQL,什么时候该用ES呢?
  6. SeDuMi教程(1)
  7. 信息搜集之常见的web组合
  8. Python多线程好玩弹窗代码
  9. Java毕业设计-资产管理系统
  10. 朗强:HDMI分配延长器的作用
  11. windows10系统平移到新的硬盘(修复引导区)
  12. python 同步记事本_如何使用Python同步文件夹
  13. SAS中的intnx函数
  14. 第三篇第二章室内外消防给水系统
  15. 如何高效设计游戏——游戏伤害公式的量身定做
  16. ShardingSphere实践(1)——ShardingSphere介绍
  17. SSH2远程连接例子
  18. FreeMarker 输出Boolean类型变量默认值
  19. C语言——register
  20. php aes解密中文,PHP AES加密解密算法

热门文章

  1. 【Nginx】输出/返回 HelloWorld
  2. Nutch开发(三)
  3. qt tcp通信_Qt之网络编程TCP通信
  4. 计算机的键盘功能,电脑键盘功能
  5. html新年倒计时代码_js实现倒计时
  6. html 注册插件,HTML 插件
  7. raid卡缓存对硬盘性能_Mac Pro 2019加装2.5英寸机械硬盘方案
  8. 嘘,Python 优化提速的 8 个小技巧
  9. 为什么 Django 框架持续统治着 Python 开发?
  10. python 小例子 源码 莫凡_100 个 Python 小例子(一)