不要在构造或析构的过程中调用虚函数

C++在程序进行构造或析构期间,你绝不能调用虚函数,这是因为这样的调用并不会按你所期望的执行。C++中,如果在某个类的构造函数或者构造过程中调用了某个虚函数,该调用不会完全按照虚函数的多态性调用到其派生类的重写的函数,而只会调用到本类这个函数。下面是一个例子: 

例1:
class B
{
public :
    B()
    {
        f();
    } 
    virtual void f()
    {
        cout<<"B::f()"<<endl;
    }
};
 
class D1:public B
{
public :
   D1()
    {
    };
    void f()
    {
        cout<<"D1::f()"<<endl;
    }
}; 
 
int main(int argc, char* argv[])
{
    D1 d;
    system("pause");
   return 0;
}
以上代码,运行输出为:B::f()

上面的例子稍微改变一下,比较隐蔽的一个例子:

例2:
class B
{
public :
    B()   { } 
    void t()
    {
        f();
    } 
    virtual void f()
    {
        cout<<"B::f()"<<endl;
    }
};
 
class D1:public B
{
public :
   D1()
    {
        t();
    };
    void f()
    {
        cout<<"D1::f()"<<endl;
    }
};
 
class D2:public D1
{
public :
   D2(){};
    void f()
    {
        cout<<"D2::f()"<<endl;
    }
};
 
int main(int argc, char* argv[])
{
    D2 d;
    system("pause");
    return 0;
}
以上代码,运行输出为:D1::f()

从以上例子可以看出,某个类在构造过程中,绝不可能调用其派生类的函数,即使是虚函数。析构构成中同样。其原因,一种说法是在构造或者析构过程中,其派生类还没有创建或已经销毁,其虚函数表也不存在。所以无法调用。

在上面的例1中,如果class B中的f()定义为纯虚函数,则将是个更大的错误隐患,经测试在CB6和VC2003中编译都不会报错,运行时则会报运行时错误。如,VC报:pure virtual function call。

如果你曾经是一个 Java 或 C# 的程序员,并且在最近期望返回 C++ 的怀抱,那么请你格外的注意这一条,因为在这一问题上, C++ 与其他语言走的是完全不同的两条路线。在Java中这都是没有问题的。

我就深受Java的影响,在刚开始使用C++的时候,在一个项目中写下了类似于上面例2中的代码,是多个有继承关系的VCL form之间。不过奇怪的是,在CB的VCL form中,并没有出现上面两个例子中的问题,完全和在Java中一样,完全按照我原本的期望在基类form的构造函数中调用到了其派生类的虚函数。真是歪打正着,错误的写法,居然在CB的VCL中没有问题!这也让我没有及时发现C++在这个方面和其他语言的不同。知道今天才知道!原来其中还另有隐情!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值