带有显式派生方法的C ++接口

时间:2015-03-05 03:58:16

标签: c++

我有一个示例接口,它将行为委托给实现类:

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个重载中没有一个可以转换所有参数类型

1 个答案:

答案 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.
}

这种方法通常不能很好地扩展,难以维护且容易出错。