一、public继承
”public继承“意味着is-a,即适用于base class身上的每一件事情一定也适用于derived class身上,因为每一个derived class对象也都是一个base class对象。
二、避免遮掩继承而来的名称
derived class内的名称会遮掩base class内的名称,在public继承下从来没有人希望如此。为了让被遮掩的名称再见天日,可使用using声明式。
举例说明如下:
class Base {
public:
virtual void mf() = 0;
virtual void mf(int i);
};
class Derived : public Base {
public:
virtual void mf();
};
Derived d;
int x;
d.mf(); //没问题,调用Derived::mf
d.mf(x); //错误,因为Derived::mf遮掩了Base::mf
class Derived : public Base {
public:
using Base::mf; //让Base class内名为mf的所有东西在Derived作用域内都可见(并且public)
virtual void mf();
};
Derived d;
int x;
d.mf(); //没问题,调用Derived::mf
d.mf(x); //没问题,调用Base::mf
三、区分接口继承和实现继承
在public继承之下,derived class总是继承base class的接口。
pure virtual函数、simple(impure) virtual函数、non-virtual函数之间的差异,使你得以精确指定你想要derived class继承的东西:只继承接口、继承接口和一份缺省实现、继承接口和一份强制实现。
四、不重新定义继承而来的non-virtual函数
绝不要重新定义继承而来的non-virtual函数,否则违反了基类”不变性凌驾特异性“的性质,如果真要如此应该在基类中定义virtual函数。
五、不重新定义继承而来的缺省参数值
绝不要重新定义一个继承而来的缺省参数值,因为缺省参数值都是静态绑定,而virtual函数——你唯一应该覆写的东西——却是动态绑定。
六、通过复合朔模出has-a或”根据某物实现出”
复合是类型之间的一种关系,当某种类型的对象内含它种类型的对象,便是这种关系,例如:
class Address {...}; //某人地址
class Person {
public:
...
private:
Address address; //复合成分
std::string name;
};
在应用领域,复合意味着has-a;在实现领域,复合意味着根据某物实现出。
七、private继承
private继承遵循如下两条规则:
(1)编译器不会自动将一个derived class对象转换为一个base class对象。举例如下:
class Person {...};
class Student : private Person {...};
void eat(const Person& p);
Person p;
Stduent s;
eat(s); //错误,因为父子类之间不是像public继承时一样的is-a的关系
(2)由private base class继承而来的所有成员,在derived class中都会变成private属性,纵使它们在base class中原本是protected或public属性。
从实现的角度来说,private继承具有has-a的意义,但跟复合带来的has-a还是有一定的区别的:
(1)继承时编译器可以进行空基类优化,这点可以参考我的这篇博文《
C++之对象大小》,这是其相比复合的优势。
(2)private继承后可以在derived class中访问base class的protected成员,也可以重新定义其virtual函数,这是其相比复合的优势。
(3)private继承意味着的derived class对象不能访问base class中的函数,因为变成私有的了,也就是
private继承意味着只有实现部分被继承,而接口部分应略去,这是其相比复合的劣势。
需要注意的是:虽然private继承有时也有一定的优势,但“明智而审慎地使用private继承”是必要的,只有在考虑完所有方案后,发现其仍然是“表现程序内两个class之间关系”的最佳方案时,才使用它。
阅读(3609) | 评论(13) | 转发(3) |