4

视觉工作室 2013。

鉴于:

class base_1
{
public:
    virtual void foo(int) = 0;
};

class base_2
{
public:
    virtual void foo(int, double) = 0;
};

class join_1_2 : public virtual base_1, public virtual base_2
{};

我有一个水槽:

void sink(join_1_2 &param)
{
    param.foo(42, 3.14);
}

但我得到以下编译器错误:

错误 C2385:“foo”的不明确访问

可能是基础“base_1”中的“foo”

或者可能是基础“base_2”中的“foo”

错误 C2660:“base_1::foo”:函数不接受 2 个参数

错误 C3861:“foo”:找不到标识符

我知道我可以通过以下方式解决此问题:

param.base_2::foo(42, 3.14);

但正如你可以想象的那样,虚拟继承已经是我不得不忍受的一种罪过。我可能会写一个适配器。但我不明白是什么阻止了编译器尝试解析 base_2 中的 foo。我的同事认为这是编译器错误,但我并没有这么快责怪供应商。

C++ 规范对跨基类解决重载虚方法有什么看法?

4

2 回答 2

4

根据标准,这确实是模棱两可的,但是您可以using明确地使用或指定基类:

class join_1_2 : public virtual base_1, public virtual base_2
{
public:
    using base_1::foo;
    using base_2::foo;
};

void sink(join_1_2 &param)
{
    param.base_2::foo(42, 3.14);
}

7.3.3 using 声明

出于重载决议的目的,通过 using 声明引入派生类的函数将被视为派生类的成员。

于 2015-12-16T23:06:53.090 回答
4

经验法则是不同范围内的函数不会重载——这里我们foo的 s 在不同的范围内。如果您希望它们重载,您需要使用 using-declaration将它们引入:

class join_1_2 : public virtual base_1, public virtual base_2
{
public:
    using base_1::foo;
    using base_2::foo;
};
于 2015-12-16T23:18:09.477 回答