(1)
public 继承意味着“is-a”的关系,但是有时候会有特殊情况,比如:企鹅是一种鸟,鸟会飞,所以我们以为代码是:
class Bird{
public:
virtual void fly();
...
};
class Penguin:public Bird{
...
};
但是企鹅不会飞,在鸟类中有几种鸟不会飞,就像大多数算法没有回调这种功能,但有一些算法会有这种功能,这时候我们可以这样写:
class Bird{
...
};
class FlyingBird:public Bird{
public:
virtual void fly();
...
};
class Penguin:public Bird{
...
};
这样写也有缺陷,对于一些软件系统而言不需要区分鸟会不会飞,如果软件系统主要处理鸟的其他特性,完全不在乎飞行就不需要这样写。这也反映出一个事实,世界上并不存在一个“适用于所有软件”的完美设计,所谓最佳设计,取决于系统希望做什么事。
另外两种写法是:
a.
class Penguin:public Bird{
public:
virtual void fly() {
error { "wrong!" };
}
...
};
b.
不能为penguin定义fly函数
class Bird {
...
};
class Penguin:public Bird {
...
};
如果让企鹅飞就会报错:
Penguin p;
p.fly();
相比于第一种方法,第二种会更好,因为好的接口可以防止无效代码通过编译,相比于在运行时报错,在编译时报错会更好。
“public 继承”意味着“is-a”。适用于base classes身上的每一件事情一定也适用于derived classes身上,因为每一个derived class对象也都是一个base class对象。
(2)
区分接口继承和实现继承;
a.pure virtual 函数只具体指定接口继承;
b.impure virtual函数具体指定接口继承及缺省实现继承;
c.non-virtual函数具体指定接口继承以及强制性实现继承;
关于b有时会有一种错误,如果子类没有自己重写impure virtual函数,就会自动调用基类的impure virtual缺省实现,如果子类的实现跟基类一样还好,如果不一样就会出错。所以有一种改进方法是把基类的impure virtual函数改为pure virtual函数,强制子类自己实现,基类的缺省改为protected下的函数,子类的实现如果和基类一样就可以在子类的实现中inline调用基类protected下的函数。