类的继承实现了is-a关系,但不适用于has-a关系。比如学生和成绩的关系,午餐和青菜的关系等。一种方案是成为包含、组合或是层次化的关系;另一种是使用私有或保护继承。
组合(或包含)关系,即创建一个包含其它类对象的类。使用组合,类可以获得实现,但不能获得接口。
实现组合关系,其初始化通常用成员初始化列表方法。注意用初始化列表包含多个项目时,被初始化的顺序为它们被声明的顺序,而不是它们在初始化列表中的顺序。
私有继承,基类的公有成员和保护成员都将成为派生类的私有成员,公有方法都将成为派生类的私有方法。意味着基类方法将不会成为派生类对象公有接口的一部分,但可以在派生类的成员函数中使用它们。故也是获得实现,但不获得接口。格式如:
class Student : PRivate std::string, private std::valarray<double>
记住private继承是默认值,如果公有继承应该用public关键字!
使用包含关系,将提供被显式命名的对象成员,而私有继承则提供了无名称的子对象成员。因此在用成员初始化列表初始化时,私有继承的版本应该使用类名而不是成员名来标识构造函数。如要调用基类方法,包含关系的版本通过使用对象成员来调用,而私有继承版本使用类名和作用域解析运算符来调用。
综上,包含和私有继承都能建立has-a关系。包含关系简单直观,应优先使用。而私有继承有更多特性,如派生类可以使用基类的保护成员;允许派生类重新定义从基类那里继承的虚函数等。
保护继承是私有继承的变体,关键字为protected,基类的公有成员和保护成员都将成为派生类的保护成员。在第三代类中可以看出保护继承与私有继承的区别。使用私有继承,第三代类不能使用基类接口,因其在派生类中已经变成私有方法;而使用保护继承,基类公有方法在第二代中变成受保护的,因此第三代类可以使用它们。
新闻热点
疑难解答