C++构造函数调用虚函数

来源:互联网 发布:java运行原理 编辑:程序博客网 时间:2024/06/05 14:37

Effective C++中提到,尽量不要再构造函数中调用虚函数,主要是构造函数首先需要调用基类的构造函数,此时对象尚未初始化完成,因此还是作为基类,所以基类调用的虚函数是基类本身的。只有在初始化完成之后,对象才能够调用新的虚函数。

通常,从构造函数的内部调用所有成员函数是安全的,因为该对象在用户代码的第一行执行之前已完全设置(已初始化虚拟表等) 但是,在构造或析构期间,成员函数调用抽象基类的虚拟成员函数可能是不安全的。构造函数可以调用虚函数。 调用虚函数时,调用的函数将是为构造函数自己的类定义的函数(或从其基类继承)。 以下示例演示从构造函数的内部调用虚函数时发生的情况:

// specl_calling_virtual_functions.cpp// compile with: /EHsc#include <iostream>using namespace std;class Base{public:    Base();             // Default constructor.    virtual void f();   // Virtual member function.};Base::Base(){    cout << "Constructing Base sub-object\n";    f();                // Call virtual member function}                       //  from inside constructor.void Base::f(){    cout << "Called Base::f()\n";}class Derived : public Base{public:    Derived();          // Default constructor.    void f();           // Implementation of virtual};                      //  function f for this class.Derived::Derived(){    cout << "Constructing Derived object\n";}void Derived::f(){    cout << "Called Derived::f()\n";}int main(){    Derived d;}


在运行前面的程序时,声明 Derived d 将产生以下事件序列:

  1. 调用类 Derived (Derived::Derived) 的构造函数。

  2. 在输入 Derived 类的构造函数的主体之前,调用类 Base (Base::Base) 的构造函数。

  3. Base::Base 调用函数 f,该函数是一个虚函数。 通常,将调用 Derived::f,因为对象 d 属于类型 Derived 由于 Base::Base 函数是构造函数,因此该对象不属于 Derived类型,并且将调用 Base::f

另一个例子:

#include<iostream>using namespace std;class Base{public:    Base():x(12)    {        foo();    }    virtual void foo(int a = 43)    {        cout<<"Base" << a << endl;    }int x ;};class Derived:public Base{public:    Derived():y(13)    {        foo();    }    virtual void foo(int a = 12)    {        cout<<"Derived" << a << endl;    }int y ;};int main (){Derived d;d.foo();Base &p = d;p.foo();getchar();}

输出的结果是:Base 43 \n Derived 12 \Derived 43;

第一个是调用父类的foo,输出Base43,Derived 构造函数中执行foo()的时候,Derived此时已经构造成功了,因此调用的是foo,至于为什么出书的值是Derived12,因为这个直接调用的是子类的,不存在动态静态绑定之类的,第三个输出的而是Derived 43,由于是引用调用的foo,因此存在动态绑定。在C++中,动态绑定的时候,调用的是对象的虚函数,但是默认参数是静态绑定的。。所以输出的是Derived43;


最害怕的是半吊子。。懂一半。。

参考http://msdn.microsoft.com/zh-cn/library/s8e39b8h.aspx


0 0
原创粉丝点击