首页 > 代码库 > C++ Primer 学习笔记_97_用于大型程序的工具 --多重继承与虚继承[续2]
C++ Primer 学习笔记_97_用于大型程序的工具 --多重继承与虚继承[续2]
用于大型程序的工具
--多重继承与虚继承[续2]
七、特殊的初始化语义
从具有虚基类的类继承的类对初始化进行特殊处理:在虚基类中,由最低层派生类的构造函数初始化虚基类。在ZooAnimal示例中,使用常规规则将导致Bear 类和 Raccoon类都试图初始化Panda对象的ZooAnimal类部分。
虽然由最低层派生类初始化虚基类,但是任何直接或间接继承虚基类的类一般也必须为该基类提供自己的初始化式。只要可以创建虚基类派生类类型的独立对象,该类就必须初始化自己的虚基类,这些初始化只在创建中间类型的对象时使用。
Bear::Bear(std::string name, bool onExhibit): ZooAnimal(name, onExhibit, "Bear") { } Raccoon::Raccoon(std::string name, bool onExhibit): ZooAnimal(name, onExhibit, "Raccoon") { }
虽然ZooAnimal不是Panda的直接基类,但是Panda构造函数也初始化ZooAnimal基类:Panda::Panda(std::stringname, bool onExhibit):
ZooAnimal(name, onExhibit, "Panda"), Bear(name, onExhibit), Raccoon(name, onExhibit), Endangered(Endangered::critical), sleeping_flag(false) { }
1、怎样构造虚继承的对象
Bear winnie("pooh"); Raccoon meeko("meeko"); Panda yolo("yolo");
当创建Panda对象时:
1. 首先使用构造函数初始化列表中指定的初始化式构造 ZooAnimal 部分。
2. 接下来,构造 Bear 部分。忽略 Bear 的用于 ZooAnimal 构造函数初始化列表的初始化式。
3. 然后,构造 Raccoon 部分,再次忽略 ZooAnimal 初始化式。
4. 最后,构造 Panda 部分。
如果Panda构造函数不显式初始化ZooAnimal基类,就使用ZooAnimal默认构造函数:如果 ZooAnimal 没有默认构造函数,则代码出错。
2、构造函数与析构函数次序
无论虚基类出现在继承层次中的什么地方,总是在构造非虚函数之前构造虚基类!
例如,下面毫无规律的 TeddyBear中,有两个虚基类:ToyAnimal 基类和派生 Bear 的间接基类 ZooAnimal:
class Character { //... }; class BookCharacter : public Character { //... }; class ToyAnimal { //... }; class TeddyBear : public BookCharacter,public Bear, virtual public ToyAnimal { //... };
按声明次序检查直接基类,确定是否存在虚基类。按从根类开始向下到最低层派生类的次序检查每个子树。
TeddyBear的虚基类的构造次序是先ZooAnimal再ToyAnimal。一旦构造了虚基类,就按声明次序调用非虚基类的构造函数:首先是BookCharacter,它导致调用Character构造函数,然后是Bear。因此,为了创建TeddyBear对象,按下面次序调用构造函数:
ZooAnimal(); ToyAnimal(); Character(); BookCharacter(); Bear(); TeddyBear();
在这里,由最低层派生类TeddyBear指定用于ZooAnimal和ToyAnimal的初始化式。
在合成复制构造函数中使用同样的构造次序,在合成赋值操作符中也是按这个次序给基类赋值。保证调用基类析构函数的次序与构造函数的调用次序相反。
P627 习题17.35 继承层次如图:
class Class { //... }; class Base : public Class { //... }; class Derived1 : virtual public Base { //... }; class Derived2 : virtual public Base { //... }; class MI : public Derived1,public Derived2 { //... }; class Final : public MI,public Class { //... };
//a构造次序 Class(); Base(); Derived1(); Derived2(); MI(); Class(); Final();
//a析构次序 ~Finale(); ~Class(); ~MI(); ~Derived2(); ~Derived1(); ~Base(); ~Class();
//b:一个Final对象有一个Base对象,两个Class对象。
//c Base *pb; Class *pc; MI *pmi; Derived2 *pd2; pb = new Class; //Error pmi = pb; //Error pc = new Final; //Error pd2 = pmi; //OK
//习题17.36 class Class { //... }; class Base : public Class { public: Base(); Base(std::string); Base(const Base &); protected: std::string name; //... }; class Derived1 : virtual public Base { public: Derived1():Base() {} Derived1(std::string &s):Base(s) {} Derived1(const Derived1 &d):Base(d) {} //... }; class Derived2 : virtual public Base { public: Derived2():Base() {} Derived2(std::string &s):Base(s) {} Derived2(const Derived2 &d):Base(d) {} //... }; class MI : public Derived1,public Derived2 { public: MI():Base() {} MI(std::string &s):Base(s),Derived1(s),Derived2(s) {} MI(const MI &m):Base(m),Derived1(m),Derived2(m) {} //... }; class Final : public MI,public Class { public: Final():Base() {} Final(std::string &s):Base(s),MI(s) {} Final(const Final &f):Base(f),MI(f) {} //... };
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。