在c ++中实现多个接口

时间:2013-05-20 10:07:45

标签: c++ oop

我的接口层次结构如下:

class A
{
public:
 void foo() = 0;
};

class B: public A
{
public:
void testB() = 0;
};

class C: public A
{
public:
void testC() = 0;
};

现在,我想通过相同的层次结构实现这些接口,即基类AImplBImplCImpl,但我不确定如何从相应的层次结构中派生它们接口

请帮忙。 提前谢谢。

4 个答案:

答案 0 :(得分:3)

虽然在建议多重继承之前我通常会三思而后行。如果您的需求确实没有您所说的那么复杂,那么只需虚拟地继承接口和实现。

class A
{
public:
  void foo() = 0;
};

class B: virtual public A
{
public:
  void testB() = 0;
};

class C: virtual public A
{
public:
  void testC() = 0;
};

class AImpl : virtual public A
{
 ...
}

class BImpl : virtual public B, virtual public AImpl
{
 ...
}

虚拟继承将确保AB之间只共享一个子对象AImpl。所以你应该清楚。但是,对象大小会增加。因此,如果这是一个问题,请重新考虑您的设计。

答案 1 :(得分:2)

我认为你要问的是,我如何创建一个反映我的“interace”类层次结构的第二类实现层次结构。您希望这样做以减少接口和实现之间的耦合。您的问题是您认为您的实现类应该扩展您的接口类,但也应该扩展impl类中的“自然”继承层次结构,如

   AImpl
  ^    ^
  |    |
BImpl  CImpl

我建议你看看描述这种模式的GoF(Gang of Four)Bridge pattern。 Actuall,书中的例子比维基百科上的例子要好,但似乎无法在网上找到它。这是一个粗略的(ascii)UML:

Window <>imp----------------------------> WindowImpl
^    ^                                    ^        ^
|    |                                    |        |
|   TransientWindow                       |     PMWindowImp
IconWindow                              XWindowImp

在上面的示例中,您有一个Window类,其#imp引用了该命令。因此,您的IconWindow实施将#imp引用,例如XWindowIconWindow来执行实际工作,但客户只会通过IconWindow实例引用它。这减少了重新编译的开销。

要点是:

  • 窗口类型(普通窗口,图标窗口,对话框)和窗口实现(X-windows,PMWindows)的单独类层次结构。它们可以独立扩展。
  • 操作是根据WindowImp上的抽象操作实现的。因此,操作是从平台细节中抽象出来的。
  • 如果您尝试混合抽象和多个实现,请减少出现的类的延迟。

我会留给你把它翻译成你的问题,但如果你有任何问题请发表评论。

答案 2 :(得分:1)

您可以使用单独的模板实现每个单独的接口,然后链接模板以构建派生对象,就像构建块一样。这个方法也被古老的ATL库用来实现COM接口(对于我们这些已经足够老的人来说)。

请注意,您不需要虚拟继承。

我稍微修改了一个更复杂的派生C -> B -> A示例,以显示此方法如何轻松扩展:

#include <stdio.h>

// Interfaces

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

struct B : A
{
    virtual void testB() = 0;
};

struct C : B
{
    virtual void testC() = 0;
};

// Implementations

template<class I>
struct AImpl : I
{
    void foo() { printf("%s\n", __PRETTY_FUNCTION__); }
};

template<class I>
struct BImpl : I
{
    void testB() { printf("%s\n", __PRETTY_FUNCTION__); }
};

template<class I>
struct CImpl : I
{
    void testC() { printf("%s\n", __PRETTY_FUNCTION__); }
};


// Usage

int main() {
    // Compose derived objects from templates as from building blocks.
    AImpl<A> a;
    BImpl<AImpl<B> > b;
    CImpl<BImpl<AImpl<C> > > c;

    a.foo();

    b.foo();
    b.testB();

    c.foo();
    c.testB();
    c.testC();
}

输出:

void AImpl<I>::foo() [with I = A]
void AImpl<I>::foo() [with I = B]
void BImpl<I>::testB() [with I = AImpl<B>]
void AImpl<I>::foo() [with I = C]
void BImpl<I>::testB() [with I = AImpl<C>]
void CImpl<I>::testC() [with I = BImpl<AImpl<C> >]

答案 3 :(得分:0)

class BImpl : public B {
    // code ...
}

但在B中,将函数声明为virtual,因此编译器将强制您在BImpl

中实现它们