2012-04-13 87 views
2

比方说,我有一个C++接口通过C++接口的最佳方式?

class Iface 
{ 
public: 
    virtual ~Iface() {} 
    virtual void foo() = 0; 
    virtual void bar() = 0; 
}; 

而且我有一些组类需要公开在一边实现它关闭别处。我发现相当普遍我结束了一堆的中产阶级基本上做这样的事情:

class InTheMiddleSomewhere 
    : public Iface // amongst other things 
{ 
public: // Iface 
    virtual void foo() { if (impl) impl->foo(); } 
    virtual void bar() { if (impl) impl->bar(); } 
private: 
    IfaceImpl* impl; 
}; 

它得到烦人编写和维护的接口扩展,增殖和变化。

问:是否有更好的(或多或少的自动)方法来实现完整接口的传递,而不是手动编写所有“if(impl)impl - > ...”东西?

+1

派生创建一个类做它与私有继承, 。 – 2012-04-13 13:58:35

+1

可以将'impl'声明为'Iface *'而不是'IfaceImpl *'吗? – dasblinkenlight 2012-04-13 13:59:13

+0

@彼得,非常好的评论,尽管它只解决了部分问题。 (你仍然愿意为每种方法编写它),并且有一些中间类可能想要做些稍微不同的事情的弱点。我真正想要的是“这里有两件完全相同的东西,把它们绑在一起*就像这样*”template/macro/whatever。 – idij 2012-04-13 14:21:42

回答

1

您可以将调用绑定到一个函数对象中,然后仅传递函数对象(而不是为接口的每个成员函数进行委托调用)。

考虑以下几点:

struct I 
{ 
    virtual R1 f1(A1, B1, ..., Z1) = 0; 
    virtual R2 f2(A2, B2, ..., Z2) = 0; 
    . 
    . 
    virtual Rn fn(An, Bn, ..., Zn) = 0; 
}; 

现在我有我的一些实施:

struct : I 
{ 
    ... 
} x, y, z; 

所以我可以打电话给X,Y和ZS功能,如:

Ri xri = x.fi(ai, bi, ..., zi); 
Ri yri = y.fi(ai, bi, ..., zi); 
Ri zri = z.fi(ai, bi, ..., zi); 

或我可以将呼叫绑定到I接口的方法如下:

function<Ri(I&)> g = bind(&I::fi, _1, ai, bi, ..., zi); 

再后来:

Ri xri = g(x); 
Ri yri = g(y); 
Ri zri = g(z); 

这个工程即使x,y和z是不同类的,只要它们是从一

+0

它会如何精确地工作,你能扩展吗?据推测InTheMiddle不再实现Iface?之后? – idij 2012-04-13 14:41:06

+0

@idij:好的更新了一些更多的信息。 – 2012-04-13 19:47:32

+0

这非常有趣。谢谢你的解释。 – idij 2012-04-13 20:43:04

0

我相信这是使用句柄类(Pimpl idiom)的一个缺点。为了支持打破/关闭原则,是否需要保持编译时间的绝对值?通常在今天的编译器和CPU中,Pimpl习惯用法不像以前那么多。

+3

该习语还用于共享库,因此实现可以更改但保留相同的接口。这对于兼容性至关重要。 – 2012-04-13 14:04:22