虚基类

来源:互联网 发布:linux自启动脚本编写 编辑:程序博客网 时间:2024/05/01 16:29

虚基类的产生:

    c++中,一个类不能多次说明为一个派生类的直接基类,但是可以不止一次的成为间接基类。这样导致了一些问题;虚基类解决了这个问题;

多继承:

    当在多继承路径上有一个公共的基类,在这些路径中的某几条路径汇合处,这个公共基类就会产生多个实例;如果想保存这个基类的一个实例,可以讲这个公共基类说明为虚拟基类;

虚基类的构造函数的条用次序:
       若在同一层次中包含多个虚基类,以及非虚基类,虚基类的构造函数在非基类之前;多个虚基类构造函数按他们说明的次调用;

      若虚基类由非基类派生,则遵守先调用基类构造函数,再调用派生类构造函数的规则;

      eg: class x:public y,virtual public z;    调用次序为 z ,y,x;

     例5-23
    class  base
                {…};
     class  base2
                  {…};
     class  level1  :   public base2,  virtual  public  base
                  {…};
     class  level2  :   public base2,  virtual  public  base
        {…};
     class  toplevel :    virtual  public level1,  public level2
                 {…};
       toplevel  view;

    当建立对象view时,将产生如下调用次序:

          level1():
               base()

               base2()

              level1()
        evel2():
              base2()
             level2()
        toplevel():
               toplevel()  

重载函数的访问是在编译时区分的,有以下三种方法:

    1.根据参数的特征加以区分,例如:
         Show(int , char)与Show(char *, float) 
     不是同一函数,编译能区分。
    2. 使用“::”加以区分,例如:
           Circle :: Show有别于Point :: Show
  3. 根据类对象加以区分。
           ACircle.Show() 调用Circle::Show()
           APoint.Show() 调用Point :: Show()
        这里ACircle和APoint分别是Circle和Point的对象。

    注意:

        1. 可以用一个指向基类的指针指向其公有派生类的对象。但是相反却不正确,即不能用指向派生类的指针指向一个基类的对象。

        2.希望用基类指针访问其公有派生类的特定成员,必须将基类指针用显式类型转换为派生类指针。例如:     ((D_class*)p)->show_phone( );(b* p;d:b)

        3.指向基类的指针p,不管是指向基类的对象base_obj还是指向派生的对象first_obj和second_obj, p->who()调用的都是基类定义的 who()的版本.必须显式地用
       first_obj.who();和second_obj.who();才能调用类first_d和类second_d中定义的who()的版本。其本质的原因在于普通成员函数的调用是在编译时静态区分。

      但是此时:若把 who()函数申明为虚函数;基类的虚函数who()定义了一种接口,在派生类中此接口定义了不同的实现版本,由于虚函数的解释机制,实现了“单界面,多实现版本”的思想。这种在运行时刻将函数界面与函数的不同实现版本进行匹配的过程,称为晚期匹配,也称为运行时的多态性。



基类函数f具有虚特性的条件是:
         1) 在基类中,将该函数说明为virtual函数。 
         2)定义基类的公有派生类。
         3) 在基类的公有派生类中原型一致地重定义该虚函数。
         4) 定义指向基类的指针变量,它指向基类的公有派生类的对象。

         class  base
  { public:
    virtual void vf1( );
  virtual void vf2( );
  virtual void vf3( );
  void f( );  };
  class derived : public  base
{  public :
   void vf1( );   虚函数的重载, 具有虚特性;
  void vf2(int); 一般函数重载,参数不同,虚拟性丢失;
  char vf3( );    一般函数重载,返回值不同,虚拟性丢失;

  void f( );       一般的函数重载,非虚函数的重载;
};

2.可以使用成员名限定可以强制使用静态联编

3.在成员函数中调用虚函数

   在一个基类或派生类的成员函数中,可以直接调用等级中的虚函数。此时,需要根据成员函数中this指针和它所指向的对象来判断调 用的是哪个函数。








   

0 0