构造函数,析构函数可不可以是虚函数?

一定要有面向对象的概念,从面向对象的角度来考虑,比如:
eg.
子类在声明一个对象时
必先调用父类的构造函数
如果父类的构造函数是个虚函数
又万一与子类中的某个函数重名、重参数列表
那该如何是好:)

从实现上看,vbtl在构造函数调用后才建立,因而构造函数不可能成为虚函数
从实际含义上看,在调用构造函数时还不能确定对象的真实类型(因为子类会调父类的构造函数);而且构造函数的作用是提供初始化,在对象生命期只执行一次,不是对象的动态行为,也没有太大的必要成为虚函数

首先你要明白:纯虚拟函数是用来提供函数接口的,虚拟函数是用来提供函数接口和默认的函数操作,非虚拟函数是用来提供函数操作的。而且你一定要记住不要在subclass中重新定义一个非虚拟函数。我想你了解了他们三者的区别,应该知道为什么了吧?
构造函数是用来构造本对象的,它肯定不能被别人重新定义,因为在别的类中是不可以访问private member的(除了friend class和function);而在继承体系中,base class的析构函数一般声明成virtual function,因为subclass要重新定义它用来摧毁object。

如果有这样两个类:
class A {
public:
  A() { a = "A"; f(); }
  virtual ~A() {}

  virtual f() { cout << a << endl; }
private:
  char* a;
};
class B : public A {
public:
  B() { b = "B"; }
  ~B() {}

  f() { cout << b << endl; }
private:
  char* b;
};
构造函数调用顺序是先调用基类构造函数,即: A(), B()
在A()中调用f(),如果按虚函数调用规则,它应该调用B::f(),但此时B还没构造(B()还没有执行),执行B::f()必然是一个错误。所以在构造函数内部执行时,对象还没有完全构造好,不能按虚函数方式进行调用,构造函数本身不能为虚函数也是相同的原因了。
构造函数和析构函数是由编译器和程序员共同完成,而类的其他成员函数是由程序员完成,所以编译器会对构造函数和析构函数给予特殊的照顾,比如它们不能有返回值,构造函数不可以是虚函数等等。
析构函数可以是虚函数,而且有的时候是必须的,基类指针指向派生类,用基类指针delete时,如果不定义成虚函数,派生类中派生的那部分无法析构。
构造函数不可以是虚函数,因为编译通不过。假如开发编译器的人让它编译通过,有意思的事情就会发生(HAHA),程序会说,我的构造函数在哪?原因是构造函数的地址在虚拟表中,而类的pvtable此时没有被初始化,pvtable可能是任何东西(pvtable初始化在构造函数中完成)

----------------------------------------------------------------------------------------------------------------------------------------------------------------------
另:

构造函数,析构函数可不可以是虚函数?

构造函数:为对象分配存储空间,使一个对象初始化;
析构函数:在该对象生命期完结时做相应的扫尾工作并释放由构造函数分配的内存;

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

自己的话:【只有基类指针指向子类对象时,虚函数才用意义。当一个基类指针指向子类对象时,子类对象已经构造好了,已经没有动态绑定的必要了,所以构造函数不能是虚函数。】
从概念上来说,如前所述,虚函数机制只有在应用于地址时才有效,因为地址在编译阶段提供的类型信息不完全。构造函数的功能是为一个对象在内存中分配空间,也就是说,此时该对象的类型已经确定了,编译系统确切的知道应该调用哪一个类的构造函数,不需要也不可能应用动态绑定。
从实现上来说,每个对象的VPTR是需要构造函数来初始化的(当然是由编译系统自动加进去的代码来实现),在构造函数没有调用之前,VPTR没有形成,根本就不可能实现动态绑定。
当构造函数内部有虚函数时,会出现什么情况呢?结果是,只有在该类中的虚函数版本被调用,也就是说,在构造函数中,虚函数机制不起作用了,调用虚函数如同调用一般的成员函数一样。


析构函数可以是虚函数:
析构函数可以是虚函数,而且应该被声明为虚函数。与一般成员函数相似,析构函数被调用时,对象的构造已经完成,VPTR和VTABLE也已被正确初始化,因此虚析构函数在实现上是可能的。
从设计角度来看,析构函数的任务是释放内存,因此它必须确切知道被释放的对象的类型,否则可能破坏有用的数据,产生不可预知的后果。例如,我们用基类指针指向了派生类对象,那么释放内存时,必须是释放派生类对象的存储空间。所以,析构函数经常被声明为虚函数。由于效率上的原因,并不把析构函数缺省为虚函数。但作为一条实践经验,可以给有虚函数的每个基类声明虚析构函数。
                                  
  当析构函数内部有虚函数时,又如何工作呢?与构造函数相同,只有“局部”的版本被调用。但是,行为相同,原因是不一样的。构造函数只能调用“局部”版本,是因为调用时还没有派生类版本的信息。析构函数则是因为派生类版本的信息已经不可靠了。我们知道,析构函数的调用顺序与构造函数相反,是从派生类的析构函数到基类的析构函数。当某个类的析构函数被调用时,其下一级的析构函数已经被调用了,相应的数据也已被丢失,如果再调用虚函数的最后一级的版本,就相当于对一些不可靠的数据进行操作,这是非常危险的。因此,在析构函数中,虚函数机制也是不起作用的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值