简体   繁体   English

从派生构造函数调用基类的虚函数

[英]Calling virtual function of base class from derived constructor

I know that calling a virtual function from constructor/destructor resolves to an early binding. 我知道从构造函数/析构函数调用虚拟函数可以解决早期绑定问题。 But I have a question here. 但是我在这里有一个问题。 Look at the below code 看下面的代码

class Base
{
    public:
    virtual void fun()
    {
        cout<<"In Base"<<endl;
    }
};

class Derived : public Base
{
    public:
    Derived(Base obj)
    {
        Base *p;
        p = &obj;
        p->fun();
    }
    void fun()
    {
        cout<<"In Derived"<<endl;
    }
};

int main()
{
    Base b;
    Derived d(b);
}

O/P is : In Base O / P是:在基地

My doubt here is, that compiler might be using dynamic binding instead of early binding. 我的疑问是,编译器可能正在使用动态绑定而不是早期绑定。 Please correct me i am wrong but i need a clear explanation of how compiler performs an early binding inside a constructor? 请纠正我,我错了,但我需要清楚地说明编译器如何在构造函数中执行早期绑定?

If the method is not a constructor the compiler will convert this statement p->fun in to something like 如果该方法不是构造函数,则编译器会将此语句p-> fun转换为类似

fetch the VPTR at run time (This vptr will have the derived class VTABLE address)

invoke method at vptr + offset 

hence the right virtual function is invoked.

but since it is a constructor, does compiler stop considering the virtual mechanism and simnply forget about the pointer type and replace the above statement p->fun() to obj.fun() (internally treating it as invoking with the appropriate object) 但由于它是构造函数,编译器是否会停止考虑虚拟机制,而会简单地忽略指针类型,并将上述语句p-> fun()替换为obj.fun()(在内部将其视为使用适当的对象进行调用)

Because even if you do early binding or late binding the result is same(invoking the local fun() ) 因为即使您进行早期绑定或后期绑定,结果也是相同的(调用本地fun())

Also if it is the local version of the function that is invoked as per the early binding mechanism inside a constructor, then how are we invoking Base version of the function which is not local to the derived (I understand derived contains base sub object but need to know the reason behind calling the base version rather than the local/derived function if the constructor performs an early binding inside a constructor for virtual functions) 另外,如果是根据构造函数内部的早期绑定机制调用的函数的本地版本,那么我们如何调用不是派生对象本地的函数的基本版本(我知道派生包含基本子对象,但需要如果构造函数在虚函数的构造函数内执行了早期绑定,则知道调用基本版本而不是本地/派生函数背后的原因)

Please help 请帮忙

因为您将实际的Base传递给创建者(而不是指针或引用),所以您拥有一个实际的Base实例-将指针强制转换为Derived*是无效的。

In your example, the constructor of Derived calls the method fun() of the object obj of type Base which you passed as parameter to Derived::Derived . 在您的示例中, Derived的构造函数调用Base类型的对象objfun()方法,您将该方法作为参数传递给Derived::Derived This has nothing to do with the instance of Derived you are constructing, hence you simply obtain a call to Base::fun() . 这与您正在构造的Derived实例无关,因此您只需获得对Base::fun()的调用。

If you instead simply call the method fun in Derived::Derived (with or without using this-> ) you will end up calling the method in Derived , see the following example: 如果您只是简单地在Derived::Derived调用fun方法(无论是否使用this-> ),您最终都会在Derived调用该方法,请参见以下示例:

#include <iostream>

class Base
{
    public:
    virtual void fun()
    {
      std::cout<<"In Base"<<std::endl;
    }
};

class Derived : public Base
{
    public:
    Derived(Base obj)
    {
      fun();
    }
    void fun()
    {
      std::cout<<"In Derived"<<std::endl;
    }
};

int main()
{
    Base b;
    Derived d(b);

    return 0;
}

Output: 输出:

In Derived

A different case (which perhaps is what you had in mind) is when you call a virtual method in the Base class. 当您在Base类中调用虚拟方法时,另一种情况(也许是您想到的)。 Then, when a Derived variable is created, the constructor of Base is invoked. 然后,在创建Derived变量时,将调用Base的构造函数。 However, at this point, Derived has not been created yet, therefore any virtual call in the costructor of the Base class will resolve to the method in Base . 但是,到目前为止,尚未创建Derived ,因此Base类的构造函数中的任何虚拟调用都将解析为Base的方法。 See the discussion here , the C++ FAQ from the website of B. Stroustrup, and the FAQ on the isocpp website. 请参阅此处的讨论, B。Stroustrup网站的C ++常见 问题解答以及isocpp网站上的常见问题解答

When finally the Derived object is created, virtual calls work as usual. 最终创建Derived对象后,虚拟调用将照常工作。

The following example illustrates this case 以下示例说明了这种情况

#include <iostream>

class Base
{
    public:
    Base() { fun(); }
    virtual void fun()
    {
      std::cout<<"In Base"<<std::endl;
    }
    void callfun() { fun(); }
};

class Derived : public Base
{
    public:
    Derived(Base obj) { }
    void fun()
    {
      std::cout<<"In Derived"<<std::endl;
    }
};

int main()
{
    std::cout << "About to create Base: ";
    Base b;
    std::cout << "About to create Derived: ";
    Derived d(b);

    std::cout << "Calling b.callfun(): ";
    b.callfun();
    std::cout << "Calling d.callfun(): ";
    d.callfun();

    return 0;
}

Output: 输出:

About to create Base: In Base
About to create Derived: In Base
Calling b.callfun(): In Base
Calling d.callfun(): In Derived

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM