C ++多重继承/虚拟继承

时间:2016-11-17 10:17:22

标签: c++ inheritance interface multiple-inheritance

对于项目,我想隐藏库接口中的一些实现细节。我在处理这种“高效”(在编码和维护方面)的唯一方法是基于相同的抽象基础对抽象和具体基类进行多重继承。所以,是的,我最终得到了一个扩展的钻石结构。

由于它的复杂性,我通常会尽量避免多重继承,所以我在使用它方面不是很有经验,因此我不确定我正在进行的设计是否有一些陷阱我不知道监督。

基本上我需要提供多个“工具”。那些“工具”当然有一些我想用接口ABC隐藏的实现细节,例如:

class Tool1Impl:public ITool1;

class Tool2Impl:public ITool2;

然而,当然这些工具有一些共性。

所以我希望有一个公共基类,但应该通过接口隐藏实现细节。

我想出了以下(钻石)计划:

            ITool                                           
          /   |   \               
        /     |     \
      /       |       \
ITool1  ToolImplBase   ITool2  ... IToolN
  \       /      \      /
   \     /        \    /
    \   /          \  /
   ToolImpl1      ToolImpl2    ... IToolImplN

ToolImplBase实现了ITool的纯虚拟功能。 ToolImpl1实现了在ITool1中声明的纯虚函数。

实施大纲如下:

class ITool {
public:
  virtual int common_foo(int a) = 0;
};

class ITool1 : public virtual ITool {
public:
  virtual int specific_foo(int b) = 0;
};

class ITool2 : public virtual ITool {
public:
  virtual int specific_bar(int c) = 0;
};

class ToolImplBase : public virtual ITool {
public:
  virtual int common_foo(int a) override;
protected:
  int _some_common_data;
};

class ToolImpl1 : public ToolImplBase, public virtual ITool1 {
public:
  virtual int specific_foo(int b) override;
private:
  int _some_specific_data;
};

class ToolImpl2 : public ToolImplBase, public virtual ITool2 {
public:
  virtual int specific_bar(int c) override;
private:
  int _some_specific_data;
};

它似乎做了我想要的,但我不确定是否有任何潜在的陷阱或明显的问题。我也不确定我是否可以在继承方案中获得“虚拟”(不是虚拟方法,而是“:public virtual”)。 一个问题是,MSVC(由于此时由于某些外部依赖性,我在2010年遇到困难)给了我编译器警告C4250:

warning C4250: 'ToolImpl1': inherits'ToolImplBase::ToolImplBase::common_foo' via dominance

我可以忽略它吗?我甚至不确定为什么我会得到这个,因为“common_foo”的非主导方式是纯虚拟的,所以实际上没有有效的“非显性”实现。

感谢您的任何输入(“ 从不 使用MI ”除外,我试图尽可能避免使用它。)< / p>

1 个答案:

答案 0 :(得分:0)

这里有关于警告的一些解释:What does C4250 VC++ warning mean?

我认为您的代码没有问题,因为您将ITool1设计为界面。

如果您在common_foo中实施ITool1功能,则在创建common_foo时,您将不知道ToolImpl1的哪个实现会有效。

您会对此问题小心,但其他任何人都可以在common_foo实施中合法实施IToolX功能而不会出错。

我的最终评论是:您为什么需要ITool1来自IToolToolImpl1已经从ToolImplBase派生,因此您的实际实现类将始终从ITool派生。

我会更改IToolX界面,如下所示

class IToolX{
    public:
    virtual int specific_foo(int b) = 0;
};