注意,当前面向对象技术的应用热点是 COM 和 CORBA,这些内容超出了 C++教 材的范畴,请阅读 COM 和 CORBA 相关论著
[[解读COM与CORBA(上)]]
[[解读COM与CORBA(下)]]
10.1 继承
如果 A 是基类,B 是 A 的派生类,那么 B 将继承 A 的数据和函数。例如:
class A { public: void Func1(void); void Func2(void); }; class B : public A { public: void Func3(void); void Func4(void); }; int main() { B b; b.Func1(); // B 从 A 继承了函数 Func1 b.Func2(); // B 从 A 继承了函数 Func2 b.Func3(); b.Func4(); return 0; }
这个简单的示例程序说明了一个事实:C++的“继承”特性可以提高程序的可复用性。
正因为“继承”太有用、太容易用,才要防止乱用“继承”。我们应当给“继承”立一些使用规则。
【规则 10-1-1】如果类 A 和类 B 毫不相关,不可以为了使 B 的功能更多些而让 B继承 A 的功能和属性。不要觉得“白吃白不吃”,让一个好端端的健壮青年无缘无故地吃人参补身体
【规则 10-1-2】若在逻辑上 B 是 A 的“一种”(a kind of ),则允许 B 继承 A 的功能和属性。例如男人(Man)是人(Human)的一种,男孩(Boy)是男人的一种。那么类 Man 可以从类 Human 派生,类 Boy 可以从类 Man 派生。
class Human { … }; class Man : public Human { … }; class Boy : public Man { … };
10.2 组合
【规则 10-2-1】若在逻辑上 A 是 B 的“一部分”(a part of),则不允许 B 从 A 派生,而是要用 A 和其它东西组合出 B。
例如眼(Eye)、鼻(Nose)、口(Mouth)、耳(Ear)是头(Head)的一部分,所以类 Head 应该由类 Eye、Nose、Mouth、Ear 组合而成,不是派生而成。如示例 10-2-1所示。
class Eye { public: void Look(void); }; class Nose { public: void Smell(void); }; class Mouth { public: void Eat(void); }; class Ear { public: void Listen(void); }; // 正确的设计,虽然代码冗长。 class Head { public: void Look(void) { m_eye.Look(); } void Smell(void) { m_nose.Smell(); } void Eat(void) { m_mouth.Eat(); } void Listen(void) { m_ear.Listen(); } private: Eye m_eye; Nose m_nose; Mouth m_mouth; Ear m_ear; };
如果允许 Head 从 Eye、Nose、Mouth、Ear 派生而成,那么 Head 将自动具有 Look、Smell、Eat、Listen 这些功能。示例 10-2-2 十分简短并且运行正确,但是这种设计方法却是不对的。
// 功能正确并且代码简洁,但是设计方法不对。 class Head : public Eye, public Nose, public Mouth, public Ear { };
一只公鸡使劲地追打一只刚下了蛋的母鸡,你知道为什么吗?
因为母鸡下了鸭蛋。
很多程序员经不起“继承”的诱惑而犯下设计错误。“运行正确”的程序不见得是
高质量的程序,此处就是一个例证。
[服务器高级架构体系:https://xxetb.xet.tech/s/4DEnTI