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

转载 2012年09月26日 13:34:42

构造函数不能声明为虚函数,析构函数可以声明为虚函数,而且有时是必须声明为虚函数。
不建议在构造函数和析构函数里面调用虚函数。


构造函数不能声明为虚函数的原因是:
1 构造一个对象的时候,必须知道对象的实际类型,而虚函数行为是在运行期间确定实际类型的。而在构造一个对象时,由于对象还未构造成功。编译器无法知道对象 的实际类型,是该类本身,还是该类的一个派生类,或是更深层次的派生类。无法确定。。。

2 虚函数的执行依赖于虚函数表。而虚函数表在构造函数中进行初始化工作,即初始化vptr,让他指向正确的虚函数表。而在构造对象期间,虚函数表还没有被初 始化,将无法进行。

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

析构函数设为虚函数的作用:
解释:在类的继承中,如果有基类指针指向派生类,那么用基类指针delete时,如果不定义成虚函数,派生类中派生的那部分无法析构。
例:
#include "stdafx.h"
#include "stdio.h"
class A
{
public:
A();
virtual~A();
};
A::A()
{
}

A::~A()
{
printf("Delete class APn");
}
class B : public A
{
public:
B();
~B();
};

B::B()
{ }

B::~B()
{
printf("Delete class BPn");
}
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. 记得在写派生类的拷贝函数时,调用基类的拷贝函数拷贝基类的部分,不能忘记了。

C/C++—— C++中构造函数不能是虚函数的原因分析

首先:到底能不能将构造函数声明为虚函数?答案是不能。
  • Linux_ever
  • Linux_ever
  • 2016年04月04日 14:08
  • 1503

虚函数/纯虚函数,以及构造函数不能是虚函数原因

1.首先要了解什么是虚函数:      简单地说,那些被virtual关键字修饰的成员函数,就是虚函数(实现多态)。          作用:指向基类的指针在操作它的多态类对象时,会根据不同的类对象,...
  • qq_33854260
  • qq_33854260
  • 2017年07月15日 11:26
  • 167

构造函数能不能是虚函数

最近有人问构造函数能不能是虚函数:当然不能解释一下: 1,从存储空间角度         虚函数对应一个vtable,这大家都知道,可是这个vtable其实是存储在对象的内存空间的。问题出来了,如果构...
  • woyaowenzi
  • woyaowenzi
  • 2008年04月21日 09:38
  • 14733

为什么C++的构造函数不可以是虚函数,而析构函数可以是虚函数

1、为什么构造函数不可以是虚函数 ①从存储空间角度     虚函数对应一个vtable,这大家都知道,可是这个vtable其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通...
  • zhang2531
  • zhang2531
  • 2016年04月22日 10:53
  • 1897

为什么构造函数不能为虚函数

1,从存储空间角度     虚函数对应一个vtable,这大家都知道,可是这个vtable其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还...
  • jiadebin890724
  • jiadebin890724
  • 2012年09月06日 16:42
  • 24940

能不能在构造函数和析构函数中调用虚函数?

可以,但是达不到想要的效果,应该尽可能避免在构造函数和析构函数中调用虚函数。 class base{ public: base(){ cout...
  • ljlstart
  • ljlstart
  • 2016年04月16日 10:52
  • 977

为什么构造函数不能够使虚函数

虚函数可谓是C++与其它的面向对象语言最大的区别了。虚函数的存在使为了多态,Java当然也有多态。不过实现方式并不是通过虚函数,我们这里就不做介绍了。         虚函数的作用主要是为了继承的时...
  • helinlin007
  • helinlin007
  • 2016年05月30日 21:46
  • 6867

C++中为什么构造函数不能为虚函数原因

1. 从存储空间角度,虚函数对应一个指向vtable虚函数表的指针,这大家都知道,可是这个指向vtable的指针其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过 vtable来...
  • u013192061
  • u013192061
  • 2015年03月18日 11:17
  • 1351

构造函数及析构函数与虚函数的关系

我们都知道构造函数不能为虚函数,而基类的析构函数一般都要定义为虚函数。今天重新复习了一下,特在此记载,以便查找。构造函数不能为虚函数主要有以下两点1、必要性分析: 当定义派生类对象时,它会主动依次调...
  • linpengbin
  • linpengbin
  • 2016年03月05日 20:38
  • 902

为什么析构函数可以为虚函数,什么情况下需要将析构函数定义为虚函数?

首先要明确: 1.每个析构函数(不加 virtual) 只负责清除自己的成员。 2.可能有基类指针,指向的确是派生类成员的情况。(这是很正常的),    那么当析构一个指向派生类成员的基类指针时...
  • jiadebin890724
  • jiadebin890724
  • 2012年09月06日 16:36
  • 8743
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:为什么构造函数不能声明为虚函数,析构函数可以
举报原因:
原因补充:

(最多只允许输入30个字)