当前位置:编程学习 > C/C++ >>

第17章 用于大型程序的工具(14)

17.3.2 转换与多个基类

在单个基类情况下,派生类的指针或引用可以自动转换为基类的指针或引用,对于多重继承也是如此,派生类的指针或引用可以转换为其任意基类的指针或引用。

在多重继承情况下,遇到二义性转换的可能性更大。编译器不会试图根据派生类转换来区别基类间的转换,转换带每个基类都一样好。

namespace Andersoft 

    namespace Animal 
    { 
        class ZooAnimal{}; 
        class Endangered{}; 
        class Bear:public ZooAnimal{}; 
        class Panda:public Bear,public Endangered{ 
        public: 
            Panda():Bear(),Endangered(){} 
        }; 
    } 

namespace Andersoft
{
 namespace Animal
 {
  class ZooAnimal{};
  class Endangered{};
  class Bear:public ZooAnimal{};
  class Panda:public Bear,public Endangered{
  public:
   Panda():Bear(),Endangered(){}
  };
 }
}
using namespace Andersoft::Animal; 
 
int _tmain(int argc, _TCHAR* argv[]) 

    ZooAnimal *za=new Panda(); 
    Endangered ea=Panda(); 
    Panda pa=Panda(); 
    Bear &ba=pa; 
    return 0; 

using namespace Andersoft::Animal;

int _tmain(int argc, _TCHAR* argv[])
{
 ZooAnimal *za=new Panda();
 Endangered ea=Panda();
 Panda pa=Panda();
 Bear &ba=pa;
 return 0;
}
1. 多重继承下的虚函数

2. 基于指针类型或引用类型的查找

像单继承一样,用基类的指针或引用只能访问基类中定义(或继承)的成员,不能访问派生类中引入的成员。

当一个类继承于多个基类的时候,那些基类之间没有隐含的关系,不允许使用一个基类的指针访问其他基类的成员。

3. 确定使用哪个析构函数

假定所有根基类都将它们的析构函数适当定义为虚函数,那么,无论通过哪种指针类型删除对象,虚析构函数的处理都是一致的。

假定这些指针每个都指向子类对象,则每种情况下发生完全相同的析构函数调用次序。析构函数调用的次序是构造函数次序的逆序。

ZooAnimal *za=new Panda(); 
delete za;  //execute ~Panda -> ~Endangered -> ~Bear 
 ZooAnimal *za=new Panda();
 delete za;  //execute ~Panda -> ~Endangered -> ~Bear17.3.3 多重继承派生类的复制控制

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

合成的赋值操作符的行为类似于复制构造函数。

合成的析构函数撤销子类对象的每个成员,并且按构造函数次序的逆序为基类部分调用析构函数。

像单继承的情况一样,如果具有多个基类的类定义了自己的析构函数,该析构函数只负责清除派生类。如果派生类定义了自己的复制构造函数或赋值操作符,则类负责复制(赋值)所有的基类子部分。只有派生类使用复制构造函数或赋值操作符的合成版本,才自动复制或赋值基类部分。

17.3.4 多重继承下的类作用域

当一个类有多个基类的时候,通过所有直接基类同时进行名字查找。多重继承的派生类有可能从两个或多个基类继承同名成员,对该成员不加限定的使用是二义性的。

1. 多个基类可能导致二义性。

2. 首先发生名字查找

即使两个继承的函数有不同的形参表,也会发生错误。类似地,即使函数在一个类中是私有的而在另一个类中是公有或受保护的,也是错误的。

3. 避免用户级二义性

可以通过指定使用哪个类解决二义性。

避免潜在二义性最好的方法是,在解决二义性的派生类中定义函数的一个版本。

namespace Andersoft 

    namespace Animal 
    { 
        class ZooAnimal{ 
        public: 
            void Print(){} 
        }; 
        class Endangered{ 
        public: 
            void Print(){} 
        }; 
        class Bear:public ZooAnimal{ 
        public: 
            void Print(){ 
            ZooAnimal::Print(); 
            } 
        }; 
        class Panda:public Bear,public Endangered{ 
        public: 
            Panda():Bear(),Endangered(){} 
            void Print(){ 
            Bear::Print(); 
            Endangered::Print(); 
            } 
        }; 
    } 

namespace Andersoft
{
 namespace Animal
 {
  class ZooAnimal{
  public:
   void Print(){}
  };
  class Endangered{
  public:
   void Print(){}
  };
  class Bear:public ZooAnimal{
  public:
   void Print(){
   ZooAnimal::Print();
   }
  };
  class Panda:public Bear,public Endangered{
  public:
   Panda():Bear(),Endangered(){}
   void Print(){
   Bear::Print();
   Endangered::Print();
   }
  };
 }
}Panda *za=new Panda(); 
za->Endangered::Print(); 
za->Print(); 

摘自 xufei96的专栏
 

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,