`
xitong
  • 浏览: 6188655 次
文章分类
社区版块
存档分类
最新评论

C++ primer第二次阅读学习笔记(第17章:用于大型程序的工具:多重继承与虚继承) .

 
阅读更多

第十七章:用于大型程序的工具:多重继承与虚继承

多重继承是从多于一个直接基类派生类的能力。多重继承的派生类继承其所有父类的属性。

为了支持多重继承,应扩充派生列表,多个类用逗号分割。如:

class panda:public bear,public animal

{

};

注意每个基类都必须制定访问级别。publicprivateprotected,与单继承一样。

多重继承的派生类对象包含每个基类子对象。

像单继承一样,多继承派生类的构造函数,可以在构造函数初始化列表中给零个或基类传递值。

各基类的构造次序由类派生列表出现的次序决定,不受构造函数初始化列表出现的顺序影响。

构造函数与析构函数调用顺序相反。

单个基类的情况下,派生类的指针或引用可以自动转换为基类的指针或引用。对于多重继承也同样。派生类的指针或引用可以转换为其任意基类的指针或引用。因此在多重继承下,遇到二义性的可能性更大。如

void print(const base1&)

void pritn(const base2 &);

base1base2derived的基类。

derived d;

print(d);//二义性。

因为此时编译器发现转换为哪个基类都一样,没有最优匹配,因此报错。

多重继承的基类的指针或引用,只能访问基类中定义的成员,不能访问派生类新引入的成员。这与单继承相同。

当一个类继承与多个基类时,不允许使用一个基类的指针访问其他基类的成员。因为它们之间没有任何关系。

多重继承下的派生类的逐个成员的初始化、赋值和析构,表现的与单继承下完全相同。派生类使用基类自己的复制构造函数、赋值操作符或析构函数隐式构造、赋值或撤销每个基类。

如果派生类定义了自己的复制构造函数或赋值操作符,则应该自己负责复制或赋值所有的基类部分。

多重继承下,会对所有直接基类进行名字查找。很有可能从两个或多个基类中继承同名的成员,在使用时必须要明确指定想要使用哪个版本,这可以通过基类名::成员,进行指定。否则将会导致二义性。

多重继承下,一个基类可以在派生类出现多次。C++使用虚继承解决这个问题。虚继承是一种机制,类通过虚继承指出它希望共享的虚基类的状态。在虚继承下,对于给定虚基类,无论该类在派生类层次中作为虚基类出现多少次,只继承一个共享的基类子对象。共享的子对象成为虚基类。

虚基类的指定可以在派生列表中通过关键字virtual设置。如

Class base1:virtual public base{};

Class base2:public virtual base{};

Class derived:public base1,public base2{};

任何可以被指定为基类的类,也可以被指定为虚基类。虚基类包含通常由非虚基类支持的任意类元素。基类为虚基类的派生类,也照样可以通过基类类型的指针或引用操纵派生类的对象。

通常每个类只初始化自己的直接基类。但是这对于虚基类却不成立。因为这样就可能导致虚基类被多次初始化的问题。为了解决这个问题,具有虚基类的派生类要特殊对待:在最低层的派生类的构造函数初始化列表中初始化虚基类。但是任何以虚基类为直接基类的类,也必须为该虚基类提供自己的初始化列表。对于上例的basebase1base2.derived类继承层次。虚基类base并没有被初始化三次,而仅仅在derived中初始化一次,因为在base1base2中均忽略对其的初始化。

在合成的默认构造函数中,无论虚基类出现在继承层次的任何地方,虚基类均先于所有其他的类构造。合成的复制构造函数使用同样的次序。因此自定义的复制构造函数和赋值操作符也应按此顺序。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics