***************************************转载请注明出处:http://blog.csdn.net/lttree********************************************
六、继承与面向对象设计
six、Inheritance and Object-Oriented Design
面向对象编程(OOP)几乎流行了两个年代,即使你过去只用C编程,现在也没办法逃脱这个趋势。
本章主要看 C++的OOP与你可能习惯的OOP的不同:
> "继承" 可以使单一继承或多重继承
> 每一个继承连接(link)可以是public,protected or private,也可以是 virtual or non-virtual
> 成员函数的各个选项:virtual?non-virtual?pure virtual?以及成员函数和其他语言特性的交互影响:缺省参数值与virtual函数有什么交互影响。
> 还有一些其他的,比如:继承如何影响C++的名称查找规则?设计选项有哪些?如果class的行为需要修改,virtual函数是最佳选择吗?
除了这些,本章还会解释C++各种不同特性的真正意义。比如:
> "public继承" 意味 "is-a"
> virtual函数 意味 "接口必须被继承";non-virtual函数 意味 "接口和实现都必须被继承"
等等
条款 32:确定你的public继承塑模出is-a关系
Rule 32:Make sure public inheritance models "is-a"
1.public继承 与 is-a
以C++进行面向对象编程,最重要的一个规则是:public inheritance(公开继承)意味"is-a"的关系
如果你令 class D("Derived")以public形式继承 class B("Base"),你便是告诉C++编译器(亦或是看你代码的人)——每一个类型为D的对象同时也是一个类型为B的对象,反之则不成立。
例如:
class Person { ... }; class Student : public Person { ... };
在C++领域中,任何函数如果期望获得一个类型为Person(或pointer-to-Person或reference-to-Person)的实参,都也愿意接受一个Student对象(或pointer-to-Student或reference-to-Student):
void eat(const Person& p); // 任何人都会吃 void study(const Student& s); // 只有学生才到校学习 Person p; // p是人 Student s; // s是学生 eat(p); // ok,p是人,可以执行吃这个动作 eat(s); // ok,s是学生,根据is-a,可以执行吃这个动作 study(s); // ok,s是学生,可以执行到校学习这个动作 study(p); // no! p是人,并非每个人都可以执行到校学习这个动作
2.产生的各种问题
>1 public继承和is-a之间的等价关系听起来非常简单,但有时候可能被误导,比如:企鹅是一种鸟,鸟可以飞,但如果我们用这样的形式来描述这种关系:
class Bird { public: virtual void fly(); // 鸟可以飞 ... }; class Penguin : public Bird { // 企鹅是一种鸟 ... };
class Bird { ... // 没有声明fly函数 }; class FlyingBird : public Bird { public: virtual void fly(); ... }; class Penguin : public Bird { ... };
void error(const std::string& msg); class Penguin : public Bird { public: virtual void fly() { error("Attempt to make a penguin fly!"); } ... };
class Rectangle { public: virtual void setHeight(int newHeight); virtual void setWidth(int newWidth); virtual int height() const; // 返回当前值 virtual int width() const; ... }; void makeBigger(Rectangle& r) { int oldHeight = r.height(); r.setWidth(r.width()+10); // 为r的宽度加10 assert(r.height()==oldHeight); // 判断r的高度是否未曾改变 }
class Square : public Rectangle { ... }; Square s; ... assert(s.width()==s.height()); // 这对于所有的正方形一定为真 makeBigger(s); // 由于public继承,s是一种(is-a)矩形 assert(s.width()==s.height()); // 对所有的正方形应该仍然为真
***************************************转载请注明出处:http://blog.csdn.net/lttree********************************************
原文地址:http://blog.csdn.net/lttree/article/details/46539337