给定遗留代码,系统具有以下类的层次结构:
Base
^
|
----------+---------------
^ ^ ^ ^ ^
| | | | |
A1 B1 C1 D1 E1
^ ^ ^ ^ ^
| | | | |
A2 B2 C2 D2 E2
.......
^ ^ ^ ^ ^
| | | | |
An Bn Cn Dn En
Run Code Online (Sandbox Code Playgroud)
层次结构表示某个特定域中的消息.
基类当然是所有消息的基类.A1..E1是属于域的版本1,A2..E2到版本2的消息,依此类推.请注意,An必须直接从An-1继承,因为An会覆盖An-1的特定方法.
所有消息都有一些共同的功能,因此它被定义为Base :: PerformFunctionality.功能的某些部分仅特定于版本n,因此存在虚函数Base :: SpecificPartOfFunctionality,它由Base :: PerformFunctionality调用.
所以我的问题是如何通过所有An..En 覆盖Base :: SpecificPartOfFunctionality.
我看到了两种可能的解决方案,我不太喜欢它们:
在每个An..En中实现Base :: SpecificPartOfFunctionality.
这个解决方案的问题是每个类的实现应该完全相同,所以我只重复代码.
另外一个问题是,如果引入了新的类Fn,开发人员可能会忘记实现SpecificPartOfFunctionality.
引入从Base派生的BaseN类,而每个An..En也派生自BaseN:
class BaseN : public Base {
//...
SpecificPartOfFunctionality() { ...}
};
class An: public An-1, public BaseN { .. }
Run Code Online (Sandbox Code Playgroud)
该解决方案的问题在于它引入了钻石问题.
如果某些其他版本m也需要覆盖Base :: SpecificPartOfFunctionality,则会出现其他问题.根据解决方案,我们将介绍BaseM,它将覆盖Base :: SpecificPartOfFunctionality.因此,这 SpecificPartOfFunctionality将被调用的 -的倍欣或倍欣.这完全是一团糟.
有什么建议?
struct Base {
virtual void PerformFunctionality() {
stuff();
SpecificPartOfFunctionality();
more_stuff();
}
private:
virtual void SpecificPartOfFunctionality() {}
};
template<class Prev>
struct Version3 : Prev {
protected: // Not private if v4's override might need to call this.
virtual void SpecificPartOfFunctionality() {
v3_specific_stuff();
}
};
struct A1 : Base {};
struct A2 : A1 {};
struct A3 : Version3<A2> {};
struct B1 : Base {};
struct B2 : B1 {};
struct B3 : Version3<B2> {};
Run Code Online (Sandbox Code Playgroud)
唯一的缺点是您无法轻松地在当前 C++ 中转发构造函数,并且为了简单起见,可能始终使用 A2 和 B2 的默认构造函数。
然而,在 C++0x 中,您可以转发构造函数:
template<class Prev>
struct Version3 : Prev {
using Prev::Prev;
//...
};
struct C2 : C1 {
C2(int); // No default constructor.
};
struct C3 : Version3<C2> {
C3() : Version3<C2>(42) {}
};
Run Code Online (Sandbox Code Playgroud)
请注意,An 必须直接继承自 An-1,因为 An 会覆盖 An-1 的特定方法。
你误解了一些东西。An 不需要直接继承自 An-1。例如,这工作得很好:
struct Example {
virtual void f();
};
template<class B>
struct Intermediate : B {};
struct Concrete : Intermediate<Example> {
virtual void f(); // Overrides Example::f.
};
Run Code Online (Sandbox Code Playgroud)
请记住,如果这不起作用,那么您的 An 首先无法从您的基类覆盖 SpecificPartOfFunctionality!在您的任何示例中, An 都不直接从 Base 继承。