条款32、确定你的public继承塑模出is-a关系
2015-03-10 20:32
302 查看
bublic继承意味着“is-a”关系。即一个D类对象(Derived)同时也是一个B类对象(Base)。D is-a B。反之则不成立。B相比D更一般化,而D相对B更特殊化。 考虑如下:
class Person {…}; class student: public Person{…};
承上,C+中任何函数期望获得类型Person(指针或引用)的实参,也愿意接受Student对象(指或引)、
void eat(const person& p); //通用行为 void study(const student& s); //学生专属行为 person p; student s; eat(p); //ok eat(s); //ok 学生也会eat study(s); //ok study(p); //错误,p不是学生
上述论点只能public继承才成立。private继承意义完全不同。
public继承和is-a之间的等价关系看起来简单,实则不然。如下鸟和企鹅的例子。
class Bird { public: virtuan void fly(); //鸟可以飞 }; clas Penguin:public Bird {…..}; //企鹅是一种鸟
我们成了语言不严谨的牺牲品,因为前提是并不是所有的鸟都会飞。
应用以下方法模拟出较佳的真实性。
class Bird { …. //没有声明fly函数 }; class flyBird : public Bird { public: virtual void fly(); …. }; class Penguin: public Bird { … //没有声明fly函数. };
虽然这样,但我们仍然未能处理好这事情,因为有些系统并不关心会飞与否的问题,这样说明了一个事实,不存在一个“适用于所有软件的设计”。
另一种思想:所有鸟会飞,企鹅是鸟,但不会飞。重新定义fly,令其产生一个运行时错误。
void error(const std::string& msg); //定义于其他某处 class Penguin:public Bird { public: virtual void fly(){error(“attempt to fly”);} … };
这里并不是说其不会飞,而是其会飞是一种错误。这是在运行期间检测出的错误。
考虑另一种思路,即“不会飞”,不可以为其定义fly函数
class Bird { …. //没有声明fly函数 }; class Penguin: public Bird { … //没有声明fly函数. };
现在,当试图飞时:
Penguin p; p.fly(); //编译器会报错误
这和上一种思想的不同之处是,第一种方法在编译期间对p.fly不会发生错误,TK18说过,好的接口可以不让无效代码通过编译,因此对比我们应该采取第二种方式 ,即在编译期间就拒绝无效代码
再考虑以下简单的公有继承,正方形public继承至矩形。我们都知道正方形是矩形,反之不然。
class Rectangle{ public: virtual void setH{int newH}; virtual void setW{int newW}; virtual int height() const; //返回当前值 virtual int width() const; … }; void makeBig(Rectangle& r) //增加r的面积 { int oldH=r.height(); r.setW(r.width()+10); //r的宽度加上0 assert(oldH==r.height()); //判断r高是否改变 }
显然,上述asser结果永远为真。因为r的高未曾改变过
现在考虑下述代码,正方公有继承矩形。则正方形被视为矩形
class Square:public Rectangle{…}; Square s; assert(s.width()==s.height()); //真 makeBig(s);//public,s is-a矩形 可以增加其面积 assert(s.width()==s.height());
很明显,按理第二个assert应该为真,但其却不同了(注意传递的是引用)
public主张的事情:
施行于基类对象的事情也能施行于派生类上,但本例矩形的方法明显不适用于正方。就如我们学过的:代码通过编译并不表示就可以正确运作。
is-a并不是唯一存在的类之间的关系。另外的有has-a(有一个)和is-implemented-in-terms-of(根据某物实现出),将这些作为is-a都是错误的。所以应该确实了解这些类之间的相互关系并塑造他们。
需要记住的: 1、public继承意味着is-a。适用于base的也适用于derived.因为每个派生类对象也是一个基类对象。
相关文章推荐
- Effective C++:条款32:确定你的public继承塑模出is-a关系
- 条款32:确定你的public继承塑模出is-a 关系(Make sure public inheritacne models "is-a")
- 条款32:确定你的public继承塑模出is-a关系
- Effective C++ 条款32 确定你的public继承塑模出is-a关系
- 条款32 确定你的public继承塑模出is-a关系
- Effective C++ -----条款32:确定你的public继承塑模出is-a关系
- 条款32:确定人的public继承塑模出来is-a关系
- 条款32:确定你的public继承塑模出is-a关系
- 《Effective C++》学习笔记条款32 确定你的public继承塑模出is-a关系
- 条款32:确定你的public继承塑模出is-a关系
- 《Effective C++》之条款32:确定你的public继承塑模出is-a关系
- 条款32:确定你的public继承塑模出is-a关系
- 条款32:确定你的public继承塑模出is-a的关系
- 条款32:确定你的public继承塑模出is-a关系
- 条款32:确定你的public继承塑模出is-a关系
- 【32】确定你的public继承塑模出Is-A关系
- 条款32:确定public继承中塑造出来的是IS-A关系而不是其他的关系
- 《Effective C++》读书笔记之item32:确定你的public继承塑模出is-a关系
- Effective C++笔记_条款33确定你的public继承塑模出is-a关系
- 读书笔记_Effective_C++_条款三十二:确定你的public继承继承塑模出is-a关系