【问题标题】:Calling virtual function of base class from derived constructor从派生构造函数调用基类的虚函数
【发布时间】:2019-04-19 10:42:27
【问题描述】:

我知道从构造函数/析构函数调用虚函数会解析为早期绑定。但我在这里有一个问题。看下面的代码

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 是:在基础中

我的疑问是,编译器可能使用动态绑定而不是早期绑定。请纠正我我错了,但我需要清楚地解释编译器如何在构造函数中执行早期绑定?

如果方法不是构造函数,编译器会将此语句 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.

但是由于它是一个构造函数,编译器是否停止考虑虚拟机制并简单地忘记指针类型并将上述语句 p->fun() 替换为 obj.fun() (内部将其视为使用适当的调用对象)

因为即使您进行早期绑定或后期绑定,结果都是相同的(调用本地 fun() )

另外,如果它是根据构造函数内部的早期绑定机制调用的函数的本地版本,那么我们如何调用非派生的本地函数的基本版本(我知道派生包含基本子对象,但如果构造函数在虚函数的构造函数内部执行早期绑定,则需要知道调用基本版本而不是本地/派生函数的原因)

请帮忙

【问题讨论】:

  • objp 都是 Base(静态和动态类型)...
  • 好的。如果我用 p = this 替换 p=&obj 会发生什么;
  • 所有虚函数的虚调用(没有类名限定)都是基于动态类型而不是静态类型。这是否是“后期”绑定是一个实现问题。

标签: c++ function constructor virtual


【解决方案1】:

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

【讨论】:

  • 我认为我们永远不会遇到这样一种情况:我们不小心尝试访问构造函数内部的层次结构(派生类)的虚函数,因为这样做我们需要将派生对象传递给基类构造函数,但是当我们进入基础构造函数时,甚至还没有创建派生对象。那么为什么我们说我们不应该在构造函数中调用虚函数,这样它可能会意外地调用层次结构中尚未初始化的函数。如果可能的话,您能否为我提到的内容提供一个小代码 sn-p。谢谢您的帮助。
  • @user2906818 我不知道你在问什么,但我认为你得到了“this”并且参数混淆了如果你通过引用将构造的 Derived 对象传递给构造函数当然你可以调用 virtual对参数起作用,但对 this 不起作用。
  • 只是补充一下-问题中的代码甚至没有什么隐晦的棘手之处。该参数是Base 对象而不是Derived,因此显然调用了基本虚拟。甚至指针也是一条红鲱鱼。试试obj.fun()
猜你喜欢
  • 2011-09-27
  • 2018-07-21
  • 2016-07-19
  • 2018-07-16
  • 1970-01-01
  • 2015-08-18
  • 2011-05-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多