我有一个示例接口,它将行为委托给实现类:
class IBase
{
public:
virtual void Do(IBase* base) = 0;
virtual std::string name() = 0;
};
然后我有1..N类实现IBase:
class A : public IBase
{
public:
virtual void Do(IBase* base);
virtual std::string name() { return "A"; }
};
class B : public IBase
{
public:
virtual void Do(IBase* base);
virtual std::string name() { return "B"; }
};
然后我希望Do()方法的主体调用为实现IBase的所有内容定义的自由方法:
void method(A* a, B* b)
{
std::cout << a->name() << " " << b->name() << std::endl;
}
void method(B* b, A* a)
{
method(b, a);
}
这不能编译因为使用此代码,因为IBase无法解析为派生类型:
void Test::Run()
{
IBase* a = new A();
IBase* b = new B();
b->Do(a);
}
我如何使这项工作或类似的东西?免费方法实现了所有可能的组合,似乎有一个技巧可以让IBase *在其中一个重载中被接受。
其次,如何实现一个接口方案,其中每个实现者都有一个接口的共享方法?也许这可以通过免费方法更好地实现,并从IBase接口中删除Do(IBase *)。
编辑: 它是有效的,如果(a)被声明为类型A.什么是使上述代码与IBase一起工作的最佳方法?
void Test::Run()
{
A* a = new A();
IBase* b = new B();
b->Do(a);
}
我正在编译的文字代码:
class IBase
{
public:
virtual void Do(IBase* base) = 0;
virtual std::string name() = 0;
};
class A : public IBase
{
public:
virtual void Do(IBase* base);
virtual std::string name();
};
class B : public IBase
{
public:
virtual void Do(IBase* base);
virtual std::string name();
};
class Test
{
public:
static void Run();
};
namespace
{
void method(A* a, B* b)
{
std::cout << a->name() << " " << b->name() << std::endl;
}
void method(B* b, A* a)
{
method(b, a);
}
}
void A::Do(IBase* base)
{
method(this, base);
}
std::string A::name()
{
return "A";
}
void B::Do(IBase* base)
{
method(this, base);
}
std::string B::name()
{
return "B";
}
void Test::Run()
{
IBase* a = new A();
IBase* b = new B();
b->Do(a);
}
Visual Studio 2013:
错误1错误C2665:'anonymous-namespace'::method' : none of the 2 overloads could convert all the argument types
Error 2 error C2665: '
anonymous-namespace':: method':2个重载中没有一个可以转换所有参数类型
答案 0 :(得分:1)
所以,如果我理解正确,你希望A :: Do看起来像这样:
void A::Do(IBase* other) {
if other is A, then call:
method(this,other) for arguments A,A
else if other is B, then call
method(this,other) for arguments A,B
etc.
}
有两个答案。最好的方法通常是改变设计。使方法成为IBase中的虚函数而不是自由函数,并将特定于A和B的任何功能提取到另一个虚函数中。
class IBase
{
public:
virtual void Do(IBase* base) = 0;
virtual std::string name() = 0;
virtual void method(IBase* other);
virtual void method2() = 0;
};
void IBase::method(IBase* other) {
std::cout << name() << " " << other->method2() << std::endl;
}
另一种选择是使用类型转换:
void A::Do(IBase* other) {
if other is A, then call:
method(this,dynamic_cast<A*>(other)))
else if other is B, then call
method(this,dynamic_cast<B*>(other))
etc.
}
这种方法通常不能很好地扩展,难以维护且容易出错。