gpt4 book ai didi

c++ - 调用哪个函数? (委托(delegate)给姐妹类)

转载 作者:太空狗 更新时间:2023-10-29 20:31:22 27 4
gpt4 key购买 nike

我刚在 C++ FAQ Lite 中读到过这个

[25.10]通过虚拟继承“委托(delegate)给姊妹类”是什么意思?

 class Base {
public:
virtual void foo() = 0;
virtual void bar() = 0;
};

class Der1 : public virtual Base {
public:
virtual void foo();
};

void Der1::foo()
{ bar(); }

class Der2 : public virtual Base {
public:
virtual void bar();
};

class Join : public Der1, public Der2 {
public:
...
};

int main()
{
Join* p1 = new Join();
Der1* p2 = p1;
Base* p3 = p1;

p1->foo();
p2->foo();
p3->foo();
}

“信不信由你,当 Der1::foo() 调用 this->bar() 时,它最终会调用 Der2::bar()。是的,没错:一个 Der1 不知道的类将提供覆盖由 Der1::foo() 调用的虚函数。这种“交叉委托(delegate)”可以成为自定义多态类行为的强大技术。”

我的问题是:

  1. 幕后发生了什么。

  2. 如果我添加一个 Der3(从 Base 虚拟继承),会发生什么? (我这里没有编译器,现在无法测试。)

最佳答案

What is happening behind the scene.

简单的解释就是,因为Base的继承在Der1Der2中都是虚的,所以对象只有一个实例在最派生对象 Join 中。在编译时,假设(这是常见的情况)虚拟表作为调度机制,在编译 Der1::foo 时,它将通过虚表。

现在的问题是编译器如何为每个对象生成 vtable,Base 的 vtable 将包含两个空指针,Der1 的 vtable 将包含 Der1::foo 和一个空指针,Der2 的 vtable 将包含一个空指针和 Der2::bar [*]

现在,由于上一层的虚拟继承,当编译器处理 Join 时,它将创建一个单独的 Base 对象,因此为 创建一个单独的 vtable Join 的 >Base 子对象。它有效地合并了 Der1Der2 的 vtable,并生成一个包含指向 Der1::fooDer2::bar 的指针的 vtable

因此 Der1::foo 中的代码将通过 Join 的 vtable 分派(dispatch)到最终覆盖器,在本例中它位于虚拟继承的不同分支中层次结构。

如果你添加一个 Der3 类,并且该类定义了任何一个虚函数,编译器将无法干净地合并三个 vtables 并且会报错,并产生一些与歧义相关的错误多重定义的方法(没有覆盖程序可以被认为是最终覆盖程序)。如果将相同的方法添加到 Join,那么歧义将不再是问题,因为最终的重写器将是 Join 中定义的成员函数,因此编译器是能够生成虚拟表。

[*] 大多数编译器不会在此处编写空指针,而是指向将打印错误消息并终止 应用程序的通用函数的指针,从而比普通的段错误提供更好的诊断.

关于c++ - 调用哪个函数? (委托(delegate)给姐妹类),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4487914/

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