我想创建一个实现两个接口的类,这些接口具有同名的函数,这些函数的返回值不同。我怎么能正确地做到这一点?
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;
}
};
显式实现是私有的,因此不能直接用于类Derived
的变量。它们仍然非常有用,因为您可以将Derived
强制转换为其中一个接口以使用该实现:
var d = new Derived();
((IBase<int>)d).Method();
这可能非常有用。一个类可以多次实现ICanConvertTo以启用不同的转换。
答案 0 :(得分:3)
在Derived中使用虚拟
#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中删除虚拟 - 感谢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;
}
评论:混合静态和动态多态可能是一个糟糕的设计。
答案 1 :(得分:2)
函数只能通过返回值区分,因为编译器无法区分它们。考虑:
long x;
Derived d;
x = d.Method();
char
和int
变体都可以转换为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;
答案 2 :(得分:1)
返回值类型不是函数(方法)签名的一部分。
因此,您的两种方法被视为相同的方法(因此重新定义错误)。
所以你不能做你想做的事。你的方法应该有不同的签名。