精华内容
下载资源
问答
  • 类的多基类继承

    2013-11-01 20:11:56
    #include using namespace std; class A { private: int x; public: A ( int a = 0) { cout的构造函数被调用"; x = a; } void print() { cout; } }; class B ...public
    #include<iostream>
    using namespace std;
    class A
    {
    private:
    	int x;
    public:
    	A ( int a = 0)
    	{
    		cout<<"A的构造函数被调用"<<endl;
    		x = a;
    	}
    	void print()
    	{
    		cout<<x<<endl;
    	}
    
    };
    class B
    {
    public:
    	B ()
    	{
    		cout<<"B的构造函数被调用"<<endl;
    	}
    	void print()
    	{
    		cout<<"haha!"<<endl;
    	}
    };
    class C :public A , public B				//累c 继承了 类 A  和类 B   
    {
    private:
    	int y;
    public:
    	C ( int a = 0): A(   ), B()
    	{
    		cout<<"C的构造函数被调用"<<endl;
    		y = a; 
    	}
    	void print()
    	{
    		cout<<y<<endl;
    	}
    
    };
    int main()
    {
    	C c ( 18 );
    	c.print ();
    	c.A::print ();
    	c.B::print ();
    
    	return 0;
    }
    /*----------------------------------
    2013年11月1日 20:10:02
    好久没学习了。 最近就是不想学。。。  很乱。
    -----------------------------------------------*/

    展开全文
  • 本博客(http://blog.csdn.net/livelylittlefish)贴出作者... 多基类继承的构造函数的调用 基类窗口类、滚动条类,派生类滚动条窗口类继承这两个基类,观察其构造函数的调用代码如下:/**//**********************
    本博客(http://blog.csdn.net/livelylittlefish)贴出作者(三二一、小鱼)相关研究、学习内容所做的笔记,欢迎广大朋友指正!
       
        
    多基类继承的构造函数的调用
       
       
    基类窗口类、滚动条类,派生类滚动条窗口类继承这两个基类,观察其构造函数的调用
    代码如下:
    /************************************************************************
    * 多继承的构造函数的调用
    ***********************************************************************
    */

    #include 
    <IOSTREAM.H>

    //基类1:窗口类
    class CWindow
    {
        
    int left,top,right,bottom;
    public:
        CWindow(
    int l,int t,int r,int b)
        
    {
            left
    =l;
            top
    =t;
            right
    =r;
            bottom
    =b;
            cout
    <<"CWindow constructor! ";
        }


        
    ~CWindow(){cout<<"CWindow deconstructor! ";}
    }
    ;

    //基类2:滚动条类
    class CScrollbar
    {
        
    int left,top,right,bottom;
    public:
        CScrollbar(
    int l,int t,int r,int b)
        
    {
            left
    =l;
            top
    =t;
            right
    =r;
            bottom
    =b;
            cout
    <<"CScrollbar constructor! ";
        }


        
    ~CScrollbar(){cout<<"CScrollbar deconstructor! ";}
    }
    ;





    //派生类:滚动条窗口类
    class CScrollbarWnd :CWindow,CScrollbar
    {
    public:
        CScrollbarWnd(
    int l,int t,int r,int b);
        
    ~CScrollbarWnd();
    }
    ;

    CScrollbarWnd::CScrollbarWnd(
    int l,int t,int r,int b) : CWindow(l,t,r,b),CScrollbar(r-20,t,r,b)
    {
        cout
    <<"CScrollbarWnd constructor! ";
    }


    CScrollbarWnd::
    ~CScrollbarWnd()
    {
        cout
    <<"CScrollbarWnd deconstructor! ";
    }


    void main()
    {
        CScrollbarWnd wnd(
    100,100,400,300);
    }
       
        
    运行结果如下:
        
        
          
         
     由此可知,多基类继承时构造函数的调用顺序是从左到右,析构函数的调用顺序相反。
    展开全文
  • 继承与虚基类

    2020-03-16 19:25:04
    继承与虚基类 C++中的继承的二义性问题与虚基类的用法。在C++中类的继承非常的广泛,但当一个类继承了两个或两个以上的类的时候,如果在其继承的基类中存在相同的函数成员,在调用该函数时,就会产生不知道...

    多继承与虚基类

    C++中的多继承的二义性问题与虚基类的用法。在C++中类的继承非常的广泛,但当一个类继承了两个或两个以上的类的时候,如果在其继承的多个基类中存在相同的函数成员,在调用该函数时,就会产生不知道调用哪个基类的函数,产生二义性。通常通过在调用时加上作用域操作符(::)指明调用的基类函数便可解决。
    在这里插入图片描述
    这里再讲一种需要用到虚基类的情况,当类之间形成如下的继承关系:
    在这里插入图片描述这里的Bird和Horse都继承了Animal,然后Bird和Horse又被Pegasus继承了。那么在Pegasus调用构造函数时,会产生通过Bird继承Animal或者通过Horse继承Animal的二义性。这时需要用到虚继承来解决。当不用虚继承时,函数的调用如下:
    在这里插入图片描述
    采用虚继承即,在继承基类时在前面加上virtual。就不会出现重复调用Animal的构造函数的情况了。

    #include<iostream>
    
    using namespace std;
    
    enum COLOR{Red,Green,Blue,Yellow,White,Black,Brown};
    
    class Animal
    {
    public:
    	Animal(int);
    	virtual ~Animal() { cout << "Animal析构函数被调用...\n"; }
    	virtual int GetAge() { return itsAge; }
    	virtual void SetAge(int age) { itsAge = age; }
    private:
    	int itsAge;
    };
    
    Animal::Animal(int age) :itsAge(age)
    {
    	cout << "Animal的构造函数被调用...\n";
    }
    
    //          用虚继承解决二义性的问题
    class Horse:virtual public Animal
    {
    public:
    	Horse(COLOR color, int height,int age)
    		:Animal(age),itsColor(color),itsHeight(height)
    	{
    		cout << "Horse的构造函数被调用...\n";
    	}
    	virtual ~Horse(){ cout << "Horse的析构函数被调用...\n"; }
    	virtual void Whinny()const { cout << "Whinny!..."; }
    	virtual int GetHeight()const { return itsHeight; }
    	virtual COLOR GetColor()const { return itsColor; }
    
    private:
    	int itsHeight;
    	COLOR itsColor;
    };
    
    class Bird :virtual public Animal
    {
    public:
    	Bird(COLOR color,bool migrates,int age) 
    		:Animal(age),itsColor(color),itsMigration(migrates)
    	{
    		cout<< "Bird的构造函数被调用...\n";
    	}
    	virtual ~Bird(){cout<< "Bird的析构函数被调用...\n";}
    	virtual void Chirp()const { cout << "Chirp..."; }
    	virtual void Fly() const
    	{
    		cout << "I can fly! I can fly! I can fly!";
    	}
    	virtual bool Getmigration()const { return itsMigration; }
    	virtual COLOR GetColor() const { return itsColor; }
    
    private:
    	bool itsMigration;
    	COLOR itsColor;
    };
    
    class Pegasus :public Horse, public Bird
    {
    public:
    	void Chirp()const { Whinny(); }
    	Pegasus(COLOR, int, bool, long,int);
    	~Pegasus() { cout << "Pegasus析构函数被调用...\n"; }
    	virtual long GetNumberBelievers()const
    	{
    		return itsNumberBelievers;
    	}
    
    private:
    	long itsNumberBelievers;
    };
    
    Pegasus::Pegasus(COLOR aColor, int height, bool migrates, long numBelieve, int age)
    	:Horse(aColor, height, age),
    	Bird(aColor, migrates, age),
    	itsNumberBelievers(numBelieve)
    	,Animal(age)
    {
    	cout << "Pegasus构造函数被调用...\n";
    }
    
    int main()
    {
    	Pegasus* pPeg = new Pegasus(Red,5, true, 10,2);
    	pPeg->Fly();
    	pPeg->Whinny();
    	pPeg->Chirp();
    	cout << "有" << pPeg->GetNumberBelievers() << "人相信世界上有飞马。" << endl;
    
    	//GetColor()出现了二义性
    	//pPeg->GetColor();
    	pPeg->Horse::GetColor();
    	COLOR color=pPeg->Bird::GetColor();
    	cout << "飞马的颜色:" << color << endl;
    
    	pPeg->GetAge();
    
    	delete pPeg;
    	return 0;
    }
    

    在这里插入图片描述

    展开全文
  • C++ 继承类 虚基类

    2019-10-25 20:30:32
    1.继承派生类有基类或者虚基类,同一个类不能次作为某个派生类的直接基类,但可以作为一个派生类的间接基类; class QUEUE: STACK, STACK{/*…*/}; //错误,出现两次 class Q: S {S d;/*…*/}; //正确:采用...
    1.多继承派生类有多个基类或者虚基类,同一个类不能多次作为某个派生类的直接基类,但可以作为一个派生类的间接基类;
    class QUEUE: STACK, STACK{/*…*/}; //错误,出现两次
    class Q: S {S d;/*…*/}; //正确:采用委托d代理的方式
    
    2. 委托代理在多数情况下能够满足需要,但当对象成员和基类存在共同的基类时,就可能对同一个物理对象重复初始化(可能是危险的和不必要的);
    3.两栖机车AmphibiousVehicle继承基类陆用机车LandVehicle,委托对象成员水上机WaterVehicle完成水上功能。两栖机车可能对同一个物理对Engine初始化(启动)两次。
    class Engine{ /*...*/};
    class LandVehicle: Engine{/*...*/};
    class WaterVehicle: Engine{/*...*/};
    class AmphibiousVehicle: LandVehicle{WaterVehicle wv; /*...*/};
    
    4.仅靠多继承仍然不能解决同一个物理对象初始化两次的问题 可以采用全局变量、静态数据成员,解决同一个物理对象初始化两次的问题,而如此解决相关析构问题则更使程序逻辑复杂化。

    在这里插入图片描述

    5.上述定义存在的问题:两栖机车要安装两个引擎Engine,可引入虚基类解决该问题。
    6.虚基类
    • 虚基类用virtual声明,把多个逻辑对象映射成同一个物理对象;
    • 映射成的这个物理对象尽可能早的构造、尽可能晚的析构,构造和析构都只进行一次。若虚基类的构造函数都有参数,必须在派生类构造函数的初始化列表中列出虚基类构造参数。
    • 同一颗派生树中的同名虚基类,共享同一个存储空间;
      其构造和析构仅执行1次,
    • 有虚基类的派生类构造函数不能使用consexpr定义;
    class Engine{ /*...*/ };
    class LandVehicle: virtual public Engine{ /*...*/ };
    class WaterVehicle: public virtual Engine{ /*...*/ };
    class AmphibiousVehicle: LandVehicle, WaterVehicle { /*...*/ };
    
    继承关系

    在这里插入图片描述

    示例代码
    class Engine
    {
        int power;
    
    public:
        Engine(int p) : power(p) {}
    };
    class LandVechicle : virtual public Engine
    {
        int speed;
    public: //如从AmphibiousVehicle调用LandVehicle,则不会在此调用Engine(p)
        LandVechicle(int s, int p) : Engine(p), speed(s) {}
    };
    class WaterVechicle : virtual public Engine
    {
        int speed;
    public: //如从AmphibiousVehicle调用LandVehicle,则不会在此调用Engine(p)
        WaterVechicle(int s, int p) : Engine(p), speed(s) {}
    };
    struct AmphibiousVechicle:LandVechicle,WaterVechicle{
        AmphibiousVechicle(int s1,int s2,int p): //先构造虚基类再基类
        WaterVechicle(s2,p),LandVechicle(s1,p),Engine(p){} //整个派生树Engine(p)只1次
    };//初始化顺序: Engine(p), LandVehicle(s1, p), WaterVehicle(s2, p),而且进入两个
    //LandVehicle, WaterVehicle 后,不再初始化这两个基类的基类Engine
    
    7.派生类成员同名问题

    当派生类成员和基类成员同名时,优先访问作用域小
    的成员,即优先访问派生类的成员。当派生类数据成
    员和派生类函数成员的参数同名时,在函数成员内优
    先访问函数参数

    示例代码
    struct A{
    	int a, b, c, d;
    };
    struct B{
    	int b, c;
    	protected:
    	int e;
    };
    class C: public A, public B{
    	int a;
    	public:
    	int b; int f(int c);
    };
    int C::f(int c){
    	int i=a; //访问C::a
    	i=A::a;
    	i=b+c+d; //访问C::b和参数c,A::d
    	i=A::b+B::b; //访问基类成员
    	return A::c;
    }
    void main(void){
    	C x;
    	int i=x.A::a;
    	i=x.b; //访问C::b
    	i=x.A::b+x.B::b;
    	i=x.A::c;
    }
    
    8.析构和构造
    析构和构造的顺序相反,派生类对象的构造顺序
    • 按自左至右、自下而上地构造倒派生树中所有虚基类;
    • 按定义顺序构造派生类的所有直接基类;
    • 按定义顺序构造(初始化)派生类的所有数据成员,包括对象成员、const成员和引用成员(少数编译按程序员指定顺序);
    • 执行派生类自身的构造函数体;
    示例代码1
    #include <iostream>
    
    using namespace std;
    struct A{
        A(){ cout << "A";}
    };
    struct B{
        B(){ cout << "B";}
    };
    struct C{
        int a;
        int &b;
        const int c;
        C(char d):c(d),b(a)
        {
            a = d;
            cout << d;
        }
    };
    struct D{
        D(){ cout << "D";}
    };
    struct E:A,virtual B,C,virtual D{
        A x,y;
        B z;
        E():z(),y(),C('C'){ cout << "E";}
    };
    void test()
    {
        E e;
    }
    int main()
    {
        test();
        system("pause");
        return 0;
    }
    
    输出
    BDACAABE
    
    分析

    类E的派生图
    在这里插入图片描述

    • 依次构造e的虚基类B和D,B和D不再是派生类,执行B D构造输出函数B D;
    • 依次构造e的基类A,C,A和C不再是派生类,C有const成员,这些成员初始化不产生输出,执行A C的构造函数输出A C;
    • 依次构造e的对象成员x,y,z 输出A A B
    • 最后输出e的构造函数E;
    示例代码2
    #include <iostream>
    using namespace std;
    struct A { A() { cout << 'A'; } };
    struct B { const A a; B( ) { cout << 'B'; } }; //对象成员a将作为新根
    struct C: virtual A { C() { cout << 'C'; } };
    struct D { D() { cout << 'D'; } };
    struct E: A { E() { cout << 'E'; } };
    struct F: B, virtual C { F() { cout << 'F'; } };
    struct G: B { G() { cout << 'G'; } };
    struct H: virtual C, virtual D { H() { cout << 'H'; } };
    struct I: E, F, virtual G, H { E e; F f; I() { cout << 'I'; } };
    int main() 
    { 
    	I i;
    	return 0;
    }
    
    输出
    ACABGDAEABFHAEACABFI
    
    分析:
    1). 做出派生树

    在这里插入图片描述

    2). 构造顺序
    对象 i 有六棵派生树,树根分别为 I, a(A), a(A) , a(A) , e(E), 和f(F),同名虚基类 C 被合并;
    • 自左向右,自上而下,依次构造 I 的虚基类 C, G,D。C 和 D 不是派生类,其数据成员也不用调用构造函数,故直接执行其构造函数;G 为派生类,构造G先构造B,构造B线构造对象成员 a;构造类 C输出 C,构造类G 输出 ABG,构造G输出 ABG,构造D 输出 D;综上, 构造I的虚基类输出 CABGD;
    • 按照自左向右构造基类 E ,F, H 。E为派生类,先构造A,故构造E输出:AE;F为派生类,虚类C已经构造好,只需构造B,而B 需先构造 成员a,够构造F输出ABF;H虚基类已经全部构造完毕,只需输出 H;综上,构造 I 的基类输出 AEABFH;
    • 按定义输出构造 I 的对象成员e,f,构造 e 输出AE,构造f 输出CABF;综上,构造对象成员e , f 的输出为AECABF;
    • 最后 i 的构造体 I;
    9.类的存储空间
    • 多继承派生类包含多个基类的存储空间;
    • 如果存在虚基类和同名基类,虚基类和同名基类空间是相互独立的。
    • 如果派生类存在同名的虚基类,同一棵派生树的所有虚基类共享存储空间,虚基类通过偏移指向共享存储空间,该存储空间出现在所有直接基类之后
    • 如果基类或派生类存在虚函数,则在派生类存储空间中,包含一个单元存放虚函数入口地址表首地址;
    • 派生类的存储空间不包括基类、虚基类和对象成员的静态数据成员。
    展开全文
  • 基类

    2020-04-23 11:31:11
    当在条继承路径上有一个公共的基类,在这些路径中的某几条汇合处,这个公共的基类就会产生个实例(或个副本),若只想保存这个基类的一个实例,可以将这个公共基类说明为虚基类。 在继承中产生歧义的原因有可能是...
  • 2、了解抽象基类的基本概念以及标准库中的抽象基类;3、掌握抽象基类的使用方法。一、协议的高度动态本性1、协议与接口的基本概念协议:是Python中非正式的接口,是令Python这种动态类型语言实现多态的方式。接口:...
  • C++继承中虚基类

    2016-06-01 17:37:08
    C++中继承时,派生类难免继承两个或基类的同名函数,因此,对于派生类对象调用同名函数时便产生了二义性(该对象不知道到底调用来自于哪一个直接基类的函数)。解决办法:虚基类。 虚基类使得从个类派生出的...
  • 继承和虚基类

    2015-07-10 15:51:00
    一.继承机制存在哪些问题,怎么解决这些问题? ——歧义性:相同名称的...1.若在虚基类中定义了带参数的构造函数,而没有定义默认构造函数,则必须在所有的直接或间接派生类中使用成员初始化列表调用虚基类的构...
  • 继承基类

    千次阅读 2010-05-31 16:29:00
    测试代码: #include<iostream><br />using namespace std; class base1{ protected:  int m; public:  void show_m(){cout;} }; class base2{ protected:...
  • 关于虚基类继承

    2019-07-16 11:12:28
    但由于被继承的个父类可能直接或间接继承自一个基类,那么此时就有可能会产生一个结果,在此定义的class中包含个同一基类个副本,这种情况在大多数时候是没有意义的,反而会在逻辑上造成二义性的错误。...
  • C++继承与虚基类

    2017-04-22 15:29:26
    但是,在继承情况下,可能造成对基类中某个成员的访问出现了不唯一的情况,这时就称对基类成员的访问产生了二义性。  示 例: class base1 { public: void fun(); }; class base2 { public: void fun(); }; ...
  • 抽象基类

    2018-01-06 10:47:26
    抽象基类在你将一些共同信息导入到个其他模型的时候很有用。 你写你的基类,并在Meta类(元类)中设置abstract=True。该模型不用于生成任何数据库表。反而,当抽象基类用于其他模型的一个基类是,它的fields...
  • 基类的构造

    2009-08-20 22:12:00
    如果一个类有多个基类,基类的构造函数在继承类的构造函数之前被调用。基类的构造函数以被声明的顺序被调用。下面是一个例子: class Y ... // 继承类的构造函数 对于多基类的情况,下面是一个例子: class X : publ
  • 线程这个概念大家都很熟悉,对于winform的开发人员来说,用的还是的.但估计都是用Timer,或者backgroundWorker,为大家写了一个线程的基类,只有你用到线程拿过来就可以用了
  • C++ 继承与虚基类

    2015-03-30 22:49:00
    转载来自:CSDN ...继承的定义:派生类的基类大于一个 语法: [cpp] view plaincopy class派生类名:继承方式1基类名1,继承方式2基类名2...{<派生类新定义成员>}; 多重继承与...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,709
精华内容 6,283
关键字:

多基类