(我在此处搜索并阅读了菱形继承(钻石问题)和虚拟继承问题,但找不到答案。我的想法是这种情况有点不寻常,我愿意接受这样的想法:我的要求有所降低。另一方面,我认为这应该以“不错”的方式来实现。)
情况及要求:
我有一个C++类库,该类库无法控制,并且无法更改。它定义了一个Window
类。 Window
类具有 protected 成员(例如handle
),该成员不能通过其他方式访问,派生类打算使用该成员。 Window
定义了数百种(很多)...我不希望通过委派(例如在装饰器中)来重新实现的方法。
我想向Window
添加功能,以便派生类(我写的是LogWindow
)自动具有。这种功能的一个示例是能够将窗口彼此对齐。为了实现这一点,我需要访问Window
的 protected handle
成员。
对于我的现实生活而言,这足够了,并且解决方案很简单:从SnappableWindow
派生Window
,并从Window
派生我所有的LogWindow
派生的类(在此示例中为SnappableWindow
)。
但是,我真正想要的是,更漂亮的恕我直言,是:
Window
派生的类。 Window
派生的类,无论是否具有“可捕捉”功能,以及是否具有“最小化”功能。 Window
的受handle
保护的成员。 LogWindow
)"is" Window,"is" SnappableWindow,而"is" MinimizableWindow。 ...现在是一个问题:
通过声明
SnappableWindow
和MinimizableWindow
不是源自Window
而是在其构造函数中获取handle
,然后从LogWindow
以及Window
和SnappableWindow
的任何组合派生MinimizableWindow
,我可以获得如何做到这一点。编辑:
handle
在调用Window
的init()之后,通过LogWindow的构造函数在Window
中初始化。 (而不是通过Window
的构造函数的一半,正如我之前所说的)。但是,由于
handle
仅通过LogWindow
的构造函数进行了初始化(在它被称为Window
的init()
之后),因此我无法将SnappableWindow
和MinimizableWindow
传递为LogWindow
的构造函数初始化列表的一部分。相反,我必须在两者上显式调用一些init()
方法,并将其传递给handle
。这是在我的每个Window
派生类中。 (LogWindow
,SearchWindow
,PreferencesWindow
等)我正在寻找一种能够执行以下操作的方法:
...而不必在
LogWindow
内实现其他任何功能。我摆弄了虚拟继承,但是还不能完全解决这个问题。 最佳答案
虚拟继承应该能够处理以下问题:
class SnappableWindow: virtual public Window
class MinimizableWindow: virtual public Window
class LogWindow: virtual public Window, public SnappableWindow, public MinimizableWindow
请注意,三角形只是钻石的特例!
Window
| \ \---------------\
| \ \
| SnappableWindow MinimizableWindow
| / /
| / /-------------/
LogWindow
编辑:这是一个完整的示例:
#include <iostream>
int get_handle() { static int handle = 0; return ++handle; }
struct Window {
int handle;
Window() : handle(get_handle()) { }
};
struct SnappableWindow: virtual public Window {
SnappableWindow() { std::cout << "Snap! " << handle << std::endl; }
};
struct MinimizableWindow: virtual public Window {
MinimizableWindow() { std::cout << "Mm! " << handle << std::endl; }
};
struct LogWindow: virtual public Window, public SnappableWindow, public MinimizableWindow {
LogWindow() { std::cout << "Log! " << handle << std::endl; }
};
int main() {
LogWindow lw;
std::cout << "lw: " << lw.handle << std::endl;
}
输出:
Snap! 1
Mm! 1
Log! 1
lw: 1