(三)派生类和基类之间的特殊关系
(1)派生类对象可以使用基类的方法,条件是方法不是私有的(公有的或者是保护的)。
(2)基类指针可以在不进行显式类型转换的条件下指向派生类对象,基类引用也可以不进行显式类型转换而引用派生类对象。但是基类的指针或引用只能够调用基类的方法,不能调用派生类的方法。
这一点是符合逻辑的,比如我有一个函数,它的参数是基类对象的指针或引用,而如果我要使用这个函数处理基类的派生类对象,那么这是允许的。为什么呢?这是因为从范畴上讲,派生类应该是属于基类的,比如从树中派生出苹果树,那么苹果树肯定是属于树的。我有一个函数是处理树的,比如这个函数是种树函数,那么不管是什么树,应该都可以使用这个函数,我使用树的指针指向苹果树,从而用树的方法处理苹果树,这是没有任何问题的,也符合我们对世界的认知。
基类指针或引用可以使用派生类指针或引用,但是反过来是不可以的,比如,我不能将派生类的指针指向基类对象。
(3) Is-a关系
公有继承中,基类和派生类的关系是is a的关系,比如从水果中派生出香蕉,香蕉是一种水果就是is-a的关系。此外还有许多其他的关系,比如has a关系,午餐有香蕉,但午餐不是香蕉,因此,从香蕉中派生出午餐是不合适的,此时最好是将香蕉的对象作为一个数据成员放在午餐类中,产生has a的关系。
(4)基类指针或引用的兼容性会带来一些有趣的结果,比如我们可以用派生类的对象来初始化基类的对象,此时会调用基类的复制构造函数,将派生类中的基类部分复制给基类对象;同样,也可以将派生类对象赋值给基类对象,这会调用基类的赋值运算符,从而将派生类对象的基类部分赋值给基类对象。这两个特点的原因归根结底还是因为基类引用可以指向派生类对象,导致二者的复制构造函数和赋值运算符本来使用的是基类的const引用,结果使用了派生类的const引用了。
网友评论