gpt4 book ai didi

c++ - C++中虚拟函数的构造函数内部动态绑定(bind)

转载 作者:行者123 更新时间:2023-11-28 04:29:19 24 4
gpt4 key购买 nike

根据标准,我们知道构造函数总是在它们内部尽早绑定(bind)虚函数,因为它们不完全了解派生类层次结构的缺点。

在这种情况下,如果在我的基类构造函数中使用了早期绑定(bind),我已经将一个派生对象传递给了一个完全可以接受的基类指针(这里进行了向上转换)。如果使用早期绑定(bind),虚函数的选择应该基于指针的类型(这里是 Base *)而不是指针的内容(指针指向的对象,因为我们不知道确切的对象被指出)。在那种情况下,因为指针类型是 Base * 我们应该在这两种情况下只调用 Base 类虚函数。有人可以澄清一下吗?

我认为这里使用的是动态绑定(bind)而不是早期绑定(bind)。如果我的理解有误,请指正。

调用 base 的输出的第一行完全没问题

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

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

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

订单:

In Base
In Derived

最佳答案

构造函数体内的虚拟调用规则适用于当前正在构造的对象,因为该对象尚未被视为任何派生类的对象。 (对于当前正在销毁的对象也有类似的规则。)在使用编译时类型的意义上,它与“早期绑定(bind)”关系不大,例如语法 ClassName::member_func() 部队。

您的代码有两个不同的对象 dbd 的构造函数在您到达 p->fun(); 行。

详细说明:

  1. 程序进入main
  2. 对象 d 是使用 Derived 的隐式声明的默认构造函数创建的。
  3. Derived::Derived() 做的第一件事是通过调用默认构造函数 Base::Base() 创建基类子对象。
  4. Base::Base() 的主体调用了 fun()。由于我们尚未进入 Derived::Derived() 构造函数的主体,因此此虚拟查找将调用 Base::fun()
  5. Base::Base() 完成。
  6. Derived::Derived() 的主体是空的,执行并完成。
  7. 回到 main 中,对象 b 是通过将指向 d 的指针传递给构造函数 Base::Base(基础*)
  8. Base::Base(Base *p) 的主体调用 p->fun()。由于 p 是指向 d 的指针,它已经是一个完全构造的 Derived 类型的对象,因此此虚拟查找调用 Derived::乐趣()

对比这个稍微不同的例子,我们定义了一个Derived的默认构造函数来传递this(隐式转换为Base*)到Base 子对象的构造函数。 (这是有效的,但如果以其他方式使用指针可能会有风险,例如在 Base 的基类或成员的初始化程序中。)

#include <iostream>
using std::cout;
using std::endl;

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

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

int main()
{
Derived d;
}

这个程序将只打印“In Base”,因为现在在 Base::Base(Base *p) 中,p 确实指向当前的同一个对象 build 中。

关于c++ - C++中虚拟函数的构造函数内部动态绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53340431/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com