14-2私有继承
私有继承
使用私有继承,基类的公有成员和保护成员都将成为派生类的私有成员。这意味着基类方法不会成为派生类的公有接口的一部分,但可以在派生类的成员函数中使用。
私有继承与包含提供的特性相同,获得实现,但不获得接口。
14.2.1 Student类示例
实现私有继承
私有继承的实现需要用到关键字private,而不是public来定义类。如果不加访问限定符则默认私有继承。
class Student : private std::string, private std::valarray<double> |
使用多个类的继承称为多重继承(MI)。
1.初始化基类组件
因为继承了基类,所以需要用基类的构造函数来初始化基类部分的成员数据,而不是直接访问基类成员来初始化。
Student(const char * str, const double * pd, int n) |
2.访问基类的方法
使用包含时用对象名来调用方法,使用私有继承时用类名和解析域运算符来调用方法
double Student::Average() const |
3.访问基类对象
使用私有继承时,方法可以通过类名+解析域运算符来调用,但基类对象本身却没有名字,如何访问?
答案是使用强制类型转换。将派生类转换为基类就可以调用。
const string & Student::Name() const |
4.访问基类的友元函数
用类名显式地限定使用基类函数不适用于友元函数,因为友元不属于类。但可以通过显式地转换成基类来调用正确的函数。
ostream & operator<<(ostream & os, const Student & stu) |
14.2.2使用包含还是私有继承
正常倾向于使用包含,它易于理解。同时类中有被包含的对象名,方便调用函数。继承则会引起很多问题,尤其是多个基类继承时。
在需要多个同种类对象作为子对象时,只能使用包含,而不能使用继承,因为继承的对象没有名字无法区分彼此。
继承能提供更多特性,一种情况是类包含保护成员,这种成员在派生类中能直接使用,在包含类中却不能直接访问。另一种是需要重新定义虚函数时,只能使用继承的方式来实现,包含却不能做到。此时重定义的函数只能在类中使用,而不是公有的。
综上,通常使用包含来实现
14.2.3保护继承
保护继承是私有继承的变体。关键字:protected
class Student : protected std::string, |
当从派生类中派生出另一个类时,私有继承与保护继承之间的区别就体现出来了。
私有继承中,第三代类就不能使用基类的接口,因为基类的成员是二代派生的私有。
保护继承中,第三代类可以使用,因为基类的成员在二代派生中处于保护状态。
(详见P448表14.1)
14.2.4使用using重新定义访问权限
假设要在派生类外使用私有或保护的基类方法,可以这样做:
1.定义一个派生类方法来使用基类方法
double Student::sum() const |
2.将函数调用包含在另一个函数调用中
即使用一个using声明来指出派生类可以使用特定的基类成员
class Student : private std::string, private std::valarray<double> |
上述声明是的
valarray<double>::min()
和valarray<double>::max()
可用,使其类似于Student类的公有方法。
注:using声明只使用成员名,没有括号、函数特征标和返回类型。
同时,这使得基类的所有同名函数重载都可用