3

我想创建一个实现两个接口的类,这两个接口具有相同名称的函数,它们的返回值不同。我怎样才能正确地做到这一点?

template<class T>
class IBase
{
public:
    virtual T Method() = 0;
};

class Derived : public IBase<int>, public IBase<char> {
public:
    int _value;

    virtual int IBase<int>::Method();
    virtual char IBase<char>::Method();
};

int Derived::Method() {
    return _value;
}

char Derived::Method() {
    return _value;
}

以下是我得到的错误:

error C2555: 'Derived::Method: overriding virtual function return type differs and is not covariant from 'IBase<int>::Method

error C2556: 'int Derived::Method(void)' : overloaded function differs only by return type from 'char Derived::Method(void)'

error C2371: 'Derived::Method: redefinition; different basic types

error C2084: function 'char Derived::Method(void)' already has a body

在 C# 中,使用几乎相同的语法(称为显式接口实现)很容易做到这一点,没有任何歧义:

class Derived : IBase<int>, IBase<char> {
    int _value;

    int IBase<int>.Method() {
        return _value;
    }

    char IBase<char>.Method();
        return _value;
    }
};

显式实现是私有的,因此不能直接用于 class 的变量Derived。它们仍然非常有用,因为您可以将其Derived转换为接口之一以使用实现:

var d = new Derived();
((IBase<int>)d).Method();

这可能相当有用。一个类可以多次实现 ICanConvertTo 以启用不同的转换。

4

3 回答 3

4

在 Derived 中使用 virtual

#include <iostream>

template<typename T>
class IBase
{
    public:
    virtual T method() = 0;
};

template<typename T>
class WrapBase : public IBase<T>
{
    protected:
    virtual T do_method(T*) = 0;

    public:
    virtual T method() {
        return do_method((T*)0);
    }
};

class Derived : public WrapBase<char>, public WrapBase<int>
{
    protected:
    virtual char do_method(char*) { return 'A'; };
    virtual int do_method(int*) { return 1; };
};

在 Derived 中删除 virtual -感谢 DyP

include <iostream>

template<typename T>
class IBase
{
    public:
    virtual T method() = 0;
};

template<typename D, typename T>
class WrapBase : public IBase<T>
{
    public:
    virtual T method();
};

class Derived : public WrapBase<Derived, char>, public WrapBase<Derived, int>
{
    friend class WrapBase<Derived, char>;
    friend class WrapBase<Derived, int>;

    protected:
    char do_method(char*) { return 'A'; };
    int do_method(int*) { return 1; };
};

template<typename D, typename T>
inline T WrapBase<D, T>::method() {
    return static_cast<D*>(this)->do_method((T*)0);
}

测试:

int main () {
    Derived d;
    IBase<char>& c = d;
    IBase<int>& i = d;
    std::cout << c.method() << " != " << i.method() << std::endl;
}

评论:混合静态和动态多态性可能是一个糟糕的设计。

于 2013-08-30T10:11:10.370 回答
2

函数不能只通过返回值来区分,因为编译器无法区分它们。考虑:

long x;
Derived d;
x = d.Method();

thecharintvariant 都可以转换为long- 它应该使用哪一个?

编辑:如果你想定义转换,典型的情况是定义一个演员,例如

class X 
{
     float x;
   public:
     X(float f) : x(f) {}
     operator int() { return static_cast<int>(x); }
     operator char() { return static_cast<char>(x); }
     float getX() { return x; }
};

然后将其称为:

X x(65.3);
int y = x;
char z = x;

cout << "x.f=" << x.getF() << " as char:" << z << " as int:" << y << endl;
于 2013-08-30T09:30:15.943 回答
1

返回值类型不是函数(方法)签名的一部分。

所以你的两种方法被视为相同的方法(所以重新定义错误)。

所以你不能做你想做的事。你的方法应该有不同的签名。

于 2013-08-30T09:33:54.243 回答