【发布时间】:2017-03-31 20:01:05
【问题描述】:
对于一个项目,我想从库接口中隐藏一些实现细节。我想出处理这种“高效”(在编码和维护方面)的唯一方法是基于相同抽象基础的抽象和具体基类的多重继承。所以,是的,我最终得到了一个扩展的菱形结构。
我通常会尽可能避免多重继承,因为它很复杂,所以我在使用它方面不是很有经验,所以我不确定我提出的设计是否有一些我不知道的陷阱' t 监督。
基本上我需要提供多个“工具”。这些“工具”当然有一些我想使用接口 ABC 隐藏的实现细节,例如:
类 Tool1Impl : public ITool1;
类 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;
};
它似乎做我想做的事,但我不确定这是否有任何潜在的陷阱或明显的问题。我也不确定继承方案中的“虚拟”是否正确(不是虚拟方法,而是“:公共虚拟”)。 一个问题是,MSVC(由于一些外部依赖,我现在坚持使用 2010)给我一个编译器警告 C4250:
warning C4250: 'ToolImpl1': inherits'ToolImplBase::ToolImplBase::common_foo' via dominance
我可以忽略它吗?我什至不确定我为什么会得到这个,因为“common_foo”的非主导方式是纯虚拟的,所以实际上没有有效的“非主导”实现。
感谢您的任何意见(“从不使用 M.I.”除外,我已经尽可能避免使用它)。
【问题讨论】:
-
我的一点点:在需要时可以随意使用 MI,但是当您拥有钻石时,您可能走错了路。你确定你不是因为结果而不是意义而使用继承吗? ToolImplBase 需要考虑两件事(我不能说更多,因为示例是虚构的):组合和私有继承。
-
这个例子不是虚构的,它来自我的实际代码,当然是简化的。你会如何在这里使用这个组合?只是将 ToolImplFoo 中 ITool 的所有常用功能委托给包含的 ToolImplBase?
-
C4250函数
common_foo被2个路径继承,实现方式不同,需要最终实现 -
好吧,警告是有原因的。主导地位可能会在无意中被打破。我宁愿被警告(并决定使警告保持沉默或提供实现)但是,这是一个观点。是的,如果我能避免钻石,我会这样做。我并不是说它更好,只是更不容易出错(IMO)
标签: c++ inheritance interface multiple-inheritance