高质量程序设计指南c++/c语言(34)--多重继承

多重继承的继承列表中,一个基类只能出现一次。先看一个例子:

#include<iostream>
using namespace std;

class ZooAnimal
{
public:
    ZooAnimal()
    {
        cout << "ZooAnimal" << endl;
    }
    ZooAnimal(int data)
    {
        cout << "ZooAnimal(int data)" << endl;
        d1 = data;
    }
private:
    int d1;
};

class Bear: public ZooAnimal
{
public:
    Bear()
    {
        cout << "Bear" << endl;
    }
    Bear(int data)
    {
        cout << "Bear(int data)" << endl;
        d2 = data;
    }
private:
    int d2;
};

class Endangered
{
public:
    Endangered()
    {
        cout << "Endangered" << endl;
    }
    Endangered(int data)
    {
        cout << "Endangered(int data)" << endl;
        d3 = data;
    }
private:
    int d3;
};

class Panda: public Bear, public Endangered
{
public:  
    Panda()
    {
        cout << "Panda" << endl;
    }
    Panda(int data):Endangered(data), Bear(data)
    {
        cout << "Panda(int data)" << endl;
        d4 = data;
    }
private:
    int d4;
};

int main(void)
{
    Panda panda(10);
    return 0;
}

1、派生类构造函数初始化所有基类

// explicitly initialize both base classes
Panda::Panda(int data):Bear(data), Endangered(data){}
// implicitly use Bear default constructor to initialize base Bear
Panda::Panda(int data):Endangered(data){}

2、构造的次序

构造函数的初始化列表只能控制用于初始化基类的值,不能控制基类的构造次序。基类的构造函数是按照基类的继承顺序被调用的

 

class Panda: public Bear, public Endangered,即对Panda而言,基类初始化的顺序:
(1)ZooAnimal
(2)Bear
(3)Endangered
(4)Panda

 

3、析构的次序

总是按照构造函数运行的逆序调用析构函数,即~Panda(),~Endangered(),~Bear(),~ZooAnimal()

4、多重继承下的类作用域

     在多重继承下,成员函数中使用的名字的查找首先在函数本身进行,如果不能在本地找到名字,就继续在成员的类中查找,然后依次查找每个基类。在多重继承下,查找同时检查所有的基类继承子树---在我们的例子中,并行查找Endangered子树和Bear/ZooAnimal子树。如果在多个子树中找到改名字,则那个名字的使用必须显示的指定使用哪个基类;否则,该名字的使用是二义性的。

     假定Bear类和Endangered类都定义了一个print函数,而Panda类没有定义该函数,则 Panda panda; panda.print();这样的语句将导致编译时错误。Panda类有两个print函数是完全合法的。派生只是导致潜在的二义性,如果没有Panda对象调用print,那就可以避免二义性。如果每个print调用明确指出想要哪个版本--Bear::print还是Endangered::print,也可以避免错误。只有在存在使用该成员的二义性尝试的时候,才会出错。

     函数调用时首先发生名字查找。虽然两个继承的print成员的二义性相当明显,但是也许更令人惊讶的是,即使两个继承的函数有不同的形参表,也会产生错误。类似的,即使函数在一个类中是私有的而在另一个类中是公用的或受保护的,也是错误的。最后,如果在ZooAnimal类中定义了print而在Bear类中没有定义,调用仍是错误的。

posted on 2013-05-13 13:15  江在路上2  阅读(243)  评论(0编辑  收藏  举报