C ++中的接口,没有多重继承

时间:2014-03-12 14:24:39

标签: c++ inheritance interface

我怀疑答案是“不”或“你做错了”,但是:

是否可以实现接口类型行为而不使用C ++中的继承(11,如果重要的话)?

我有几个不同的结构,

struct Foo
{
  float A;
  void Bind() 
  { .... }
};

struct Bar
{
  float B;
  void Bind()
  {
  }
};

......和其他人

这些是通过将这些结构的数组传递给另一个进程的方法来操作的,并且它们必须非常紧密地包装。如果我使用继承,创建一个实现::Bind()方法的基类,那么后代类不仅有他们的数据,还有一个VMT,它占用了非常稀缺资源的一大部分。其他方法需要对这些不同类型进行操作,但并不真正关心数据成员或::Bind()方法的细节,这两种方法在类型之间存在很大差异。

在C#中(或者,我怀疑是java),我会做类似的事情:

interface ICommon
{
  void Bind();
}

struct Foo : ICommon
{
  void Bind() { .... };
};

struct Bar : ICommon
{
  void Bind() { ..... }
}

我可以使用模板:

template<typename T>
void Bind(T &item)
{
  item.Bind();
}

但是这引入了一些不太理想的约束(即模板需要在头部而不是cpp等中声明)。我知道有些hacks可以让你在cpp文件中放一个模板方法,但是它们有点乱,我宁愿避免它。

这可能是“有你的蛋糕,也吃它”的要求。

(请注意,这并不是其他C ++接口问题的重复,因为我试图避免使用经常推荐的使用多重继承的解决方案。)

4 个答案:

答案 0 :(得分:1)

  

是否可以实现接口类型行为而不使用C ++中的继承(11,如果重要的话)?

是。封装是继承的可行替代方案。

您使用接口来定义某些行为,然后返回接口(接口仍然是继承的,但不是由您的主类继承)。

示例:

class IBinder {
    virtual void Bind() = 0;
};

class Foo: public WhateverBaseClass {
    struct Binder: public IBinder { virtual void Bind() override {} };
    Binder b;
public:
    IBinder& getBinder() { return b; }
};

客户代码:

Foo f;
f.getBinder().Bind();

答案 1 :(得分:1)

如果您真的不想使用模板或继承,可以使用重载的自由函数:

void Bind(Foo& foo) {}
void Bind(Bar& bar) {}

int main() {
    Foo foo;
    Bar bar;
    Bind(foo);
    Bind(bar);
}

当然,任何需要对这两种类型进行操作的函数都必须过载或模板化。

答案 2 :(得分:1)

使用模板参数可以获得几乎相同的结果:

template <typename TRAIT>
class ICommon
{
  TRAIT t;

  public: void Bind()
  {
    t.Bind();
  }
}

class FooTrait
{
  public: void Bind() { .... };
};

class BarTrait
{
  public void Bind() { ..... }
}

typedef ICommon<FooTrait> Foo;
typedef ICommon<BarTrait> Bar;

template <typename T>
void call_bind(ICommon<T> x)
{
  x.Bind();
}

int main()
{
  Foo f; Bar b;
  call_bind(f);
  call_bind(b);
}

答案 3 :(得分:0)

Java的接口只是一种淡化邪恶,邪恶,交叉的心脏,我们不会做到这一点,多重继承。没什么。

对于您的问题,如果您想获得一堆共享&#34;界面的对象,&#34;做得很自然:他们属于到接口的类,即从它派生。可以创建一个(指向)这些对象的数组,甚至可以对对象本身进行一些关注(但除非绝对必要,否则我不会去那里,切掉某些东西的危险太大了。)

Re:&#34;仅在标题中使用模板&#34;:说谁?只包含头文件(可能在几个不同的源文件中),以避免反复编写相同的声明(和内联定义)。如果你需要模板或类,或者只是在一个源文件中,noboby将强制你为此创建一个标题。