c++ - 多重继承导致虚假的模棱两可的虚函数重载

标签 c++ multiple-inheritance virtual-functions overload-resolution name-lookup

在本例中,类 FooBar由图书馆提供。我的类(class)Baz继承自两者。

struct Foo
{
    void do_stuff (int, int);
};

struct Bar
{
    virtual void do_stuff (float) = 0;
};

struct Baz : public Foo, public Bar
{
    void func ()
    {
        do_stuff (1.1f); // ERROR HERE
    }
};

struct BazImpl : public Baz
{
    void do_stuff (float) override {};
};

int main ()
{
    BazImpl () .func ();
}

我得到编译错误 reference to ‘do_stuff’ is ambiguous这对我来说似乎是虚假的,因为这两个函数签名完全不同。如果 do_stuff是非虚拟的,我可以调用 Bar::do_stuff消除歧义,但这样做会破坏多态性并导致链接器错误。

我可以做func调用虚拟do_stuff没有重命名的东西?

最佳答案

名称查找和重载解析是不同的。名称必须首先在作用域中找到,即我们必须找到 X使名称do_stuff解析为 X::do_stuff -- 独立于名称的使用 -- 然后重载决议在 X::do_stuff 的不同声明之间进行选择.

该过程不是识别所有此类情况A::do_stuff , B::do_stuff等可见的,然后在其 union 中执行重载决议。相反,必须为名称标识单个范围。

在这段代码中:

struct Baz : public Foo, public Bar
{
    void func ()
    {
        do_stuff (1.1f); // ERROR HERE
    }
};
Baz不包含名称 do_stuff ,因此可以查找基类。但是名称出现在两个不同的基础中,因此名称查找无法识别范围。我们从来没有达到过重载决议。

其他答案中的建议修复有效,因为它引入了名称 do_stuffBaz的范围内,并且还为名称引入了 2 个重载。所以名称查找确定 do_stuff表示 Baz::do_stuff然后重载决议从称为 Baz::do_stuff 的两个函数中进行选择.

顺便说一句,阴影是名称查找的另一个结果(本身不是规则)。名称查找选择内部范围,因此外部范围内的任何内容都不匹配。

当依赖于参数的查找在起作用时,会出现更复杂的因素。简而言之,对于带有类类型参数的函数调用,名称查找会进行多次——我的回答中描述的基本版本,然后再对每个参数的类型进行一次。然后找到的范围的并集进入重载集。但这不适用于您的示例,因为您的函数只有内置类型的参数。

关于c++ - 多重继承导致虚假的模棱两可的虚函数重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58698154/

相关文章:

c++ - 了解虚拟继承类 vtables 和 vptr 创建

c++ - 用模板方法重写虚方法

C++:默认复制构造函数是否受到其他构造函数和析构函数的影响?

c++ - 超多重非虚拟继承中基类的作用域运算符

c++ - 派生 istringstream 并实现运算符>>(string&)

c++ - C++中多重继承的限制

c# - 事件代码是否比 C# 中的虚拟/重写方法更适合缓存?

c++ - 如何解决自定义类对象的 unordered_set 哈希函数中的这个错误?

c++ - QT4中slots如何使用自定义函数

c++ - objective c 是否需要一个标准来定义像 c++ 11 这样的内存模型?