9

也许我有两个具有相同函数名称和参数但返回值不同的接口:

struct A { virtual void foo() = 0; };
struct B { virtual int foo() = 0; };

如何定义继承此接口的 C 类(如果可能的话)?例如,我编写了一些未编译的伪代码:

// this code is fake, it doesn't compiled!!
struct C : A, B
{
    // how to tell compiler what method using if referenced from C?
    using void foo();  // incorrect in VS 2012
    // and override A::foo() and B::foo()?
    virtual void foo() { std::cout << "void C::foo();\n"; } // incorrect
    virtual int foo() { std::cout << "int C::foo();\n"; return 0; } // incorrect
 }
 // ... for use in code
 C c;
 A &a = c;
 B &b = c;
 c.foo();     // call void C::foo() when reference from C instance
 a.foo();     // call void C::foo() when reference from A instance
 b.foo();     // call int C::foo() when reference from B instance
4

4 回答 4

4

这是不可能的,但不是因为多重继承。由于fooin class的无效重载而产生歧义C。您不能同时拥有两者int foo(),并且void foo()由于返回类型不是函数签名的一部分,因此编译器将无法解析对foo. 您可以将您的接口视为AB类的联合,因此从逻辑上讲,问题在实际继承之前就已经存在。由于从编译器的角度来看A,并且B是 2 种不同且不相关的类型,因此在编译它们时没有问题,并且错误会延迟到 class 中的实际统一点C

在此处查看有关函数签名和重载的更多信息:返回类型是函数签名的一部分吗?

于 2012-11-19T22:10:34.480 回答
2

可以做的是将所有共享的东西放入一个virtual基础中,例如C_base并覆盖辅助类中的冲突virtual函数。由于共享的东西C很容易获得,C_base因此本质上就像最衍生的C. 最后,你C上课只是因为班级把事情放在一起:

struct A { virtual void foo() = 0; };
struct B { virtual int foo() = 0; };

struct C_base { int all_data; };

struct A_aux: virtual C_base, A {
    void foo() { std::cout << "A_aux::foo()\n"; }
};

struct B_aux: virtual C_base, B {
    int foo() { std::cout << "B_aux::foo()\n"; return 0; }
};

struct C : A_aux, B_aux
{
    using A_aux::foo;
};
于 2012-11-19T22:24:46.490 回答
2

您可以明确限定。

class C : A, B {
public:
    void A::foo() { ... }
    int B::foo() { ... }
};

编辑:

This appears to be an MSVC extension, rather than Standard.

于 2012-11-19T22:26:39.457 回答
1

无法使用相同的签名覆盖虚函数的返回类型(正如@icepack 的回答所解释的那样)。

另一种方法可能是使用模板基类声明foo()返回类型指定为模板参数,并提供具体返回参数类型的特化。

这将是对@Dietmar Kühl 提议的概括。

于 2012-11-19T22:23:39.003 回答