【C++学习笔记】虚基类(二)

上一期由于写累了,偷了点懒,就没把注意点放完,这次继续。
(3)若同一层次中同时包含虚基类和非虚基类,应该先调用虚基类,再调用非虚基类。(同一层中:同一级的继承中)
(4)对于多个虚基类,构造函数执行顺序任然是先左后右,先上后下。
(5)对于非虚基类,构造函数的执行顺序也是先左后右,先上后下。
(6)若虚基类由非虚基类派生而来,则仍然先调用基类构造函数,再调用派生类构造函数。

这四点体现了在同级情况下,基类、虚基类优先,先构建好基类体系,再往外派生具体成员。

虚基类的构造函数:

#include<iostream.h>
	class base {
	public:
          base(int sa)
	    {   a=sa;
	        cout<<"Constructing base"<<endl;   }
         private:
	    int a;
	};
	class base1:virtual public base{
	public:
	    base1(int sa,int sb):base(sa)
	    {    b=sb;
	         cout<<"Constructing baes1"<<endl;	    }
         private:
	    int b;
	};
	class base2:virtual public base{
	public:
	    base2(int sa,int sc):base(sa)
	    {   c=sc;
	        cout<<"Constructing baes2"<<endl;   }
	private:
	    int c;
	};
	
class derived:public base1,public base2{
public:
    derived(int h,int d):base1(h),base2(d){cout<<"derived a ="<<a+d<<endl; }
};
int main(){
    derived obj(5,8);
    return 0;
}

我们关注derived(int h,int d):base1(h),base2(d),
1.在C++中规定:虚基类子对象是由最派生类的构造函数进行初始化的。
(主函数中直接用于定义变量的类叫做最派生类,比如在例子中,derived直接在主函数中用于定义变量obj,所以它是最派生类。)
在本例中,base1和 base2的构造函数的调用是在用最派生类derived定义obj时开始调用的。

2.如果一个派生类有一个直接或间接的虚基类,那么派生类的构造函数的成员初始列表中必须列出对虚基类构造函数的调用,如果为被列出,则表示使用该虚基类的缺省构造函数来初始化派生类对象中的虚基类对象。
例子:

class base2:virtual public base{
public:
    base2(){a=5;cout<<"base2="<<a<<endl;}

    base2(int d){a=d;cout<<"base2="<<a<<endl;}
};
class derived:public base1,public base2{
public:
    derived(int h):base1(h){cout<<"derived a ="<<a<<endl; }
};

比如在本例中,最派生类构造函数没有列出base()的构造函数,所以系统就调用了第一个base2()构造函数。但是,缺省构造函数虽然名字上叫缺省构造函数,但如果你把第一个 base2(){a=5;cout<<"base2="<<a<<endl;} 删除了,系统是会报错的!

3.从虚基类直接或间接继承的派生类中的构造函数的成员初始化列表中都要列出对虚基类构造函数的调用。(这里尤其关注这个间接,就算是从虚基类派生的类中继承来的类,在写构造函数时也要列出虚基类)

  1. 最派生类的构造函数在开头已经调用了虚基类的构造函数,之后调用的其他基类的构造函数时就不会再调用这个虚基类的构造函数了。
  2. C++规定,在一个初始化列表中出现对虚基类和非虚基类的调用,则虚基类永远优于非虚基类的构造函数的执行。

最后两个小知识:

(1)关键字virtual与继承方式关键字(public或private)的先后顺序无关紧要,它只说明是“虚拟继承”。下面二个虚继承方法是等价

class  derived:virtual public base{
    //…
};
class  derived:public virtual base{
    //…
};

(2). 是一个基类在作为某些派生类虚基类的同时,又作为另一些派生类的非虚基类,这种情况允许的。下例说明了这个问题。

class  B {
    //…
};
class X:virtual  public B {
    //…
};
class Y:virtual  public B {
    //…
};
class Z:public B {
    //…
};
class AA:public X,public Y,public Z {
    //…
};

整理自浙大课程PPT,部分理解为原创

猜你喜欢

转载自blog.csdn.net/weixin_43819313/article/details/84636873