精华内容
下载资源
问答
  • 继承构造函数调用顺序 C ++中带有继承的构造函数调用的顺序 (Order of Constructor Call with Inheritance in C++) Base class constructors are always called in the derived class constructors. Whenever you ...

    继承构造函数调用顺序

    Base class constructors are always called in the derived class constructors. Whenever you create derived class object, first the base class default constructor is executed and then the derived class's constructor finishes execution.

    基类构造函数总是在派生类构造函数中调用。 无论何时创建派生类对象,都将首先执行基类的默认构造函数,然后派生类的构造函数完成执行。

    要记住的要点 (Points to Remember)

    1. Whether derived class's default constructor is called or parameterised is called, base class's default constructor is always called inside them.

      无论是调用派生类的默认构造函数还是参数化,都始终在它们内部调用基类的默认构造函数。



    2. To call base class's parameterised constructor inside derived class's parameterised constructo, we must mention it explicitly while declaring derived class's parameterized constructor.

      要在派生类的参数化构造函数内部调用基类的参数化构造函数,必须在声明派生类的参数化构造函数时显式地提及它。

    派生类构造函数中的基类Default构造函数 (Base class Default Constructor in Derived class Constructors)

    Default constructor is present in all the classes. In the below example we will see when and why Base class's and Derived class's constructors are called.

    所有类中都存在默认构造函数。 在下面的示例中,我们将看到何时以及为什么调用基类和派生类的构造函数。

    class Base
    { 
        int x;
        public:
        // default constructor
        Base() 
        { 
            cout << "Base default constructor\n"; 
        }
    };
    
    class Derived : public Base
    { 
        int y;
        public:
        // default constructor
        Derived() 
        { 
            cout << "Derived default constructor\n"; 
        }
        // parameterized constructor
        Derived(int i) 
        { 
            cout << "Derived parameterized constructor\n"; 
        }
    };
    
    int main()
    {
        Base b;        
        Derived d1;    
        Derived d2(10);
    }

    Base default constructor Base default constructor Derived default constructor Base default constructor Derived parameterized constructor

    基本默认构造函数基本默认构造函数派生的默认构造函数基本默认构造函数派生的参数化构造函数

    You will see in the above example that with both the object creation of the Derived class, Base class's default constructor is called.

    在上面的示例中,您将看到在Derived类的两个对象创建过程中,都调用了Base类的默认构造函数。

    派生类构造函数中的基类参数化构造函数 (Base class Parameterized Constructor in Derived class Constructor)

    We can explicitly mention to call the Base class's parameterized constructor when Derived class's parameterized constructor is called.

    我们可以明确提到在调用派生类的参数化构造函数时调用基类的参数化构造函数。

    class Base
    { 
        int x;
        public:
        // parameterized constructor
        Base(int i)
        { 
            x = i;
            cout << "Base Parameterized Constructor\n";
        }
    };
    
    class Derived : public Base
    { 
        int y;
        public:
        // parameterized constructor
        Derived(int j):Base(j)
        { 
            y = j;
            cout << "Derived Parameterized Constructor\n";
        }
    };
    
    int main()
    {
        Derived d(10) ;
    }

    Base Parameterized Constructor Derived Parameterized Constructor

    基本参数化构造函数派生参数化构造函数

    为什么在派生类内部调用基类构造函数? (Why is Base class Constructor called inside Derived class?)

    Constructors have a special job of initializing the object properly. A Derived class constructor has access only to its own class members, but a Derived class object also have inherited property of Base class, and only base class constructor can properly initialize base class members. Hence all the constructors are called, else object wouldn't be constructed properly.

    构造函数有适当的初始化对象的特殊工作。 派生类构造函数只能访问其自己的类成员,但是派生类对象也具有基类的继承属性,并且只有基类构造函数才能正确初始化基类成员。 因此,将调用所有构造函数,否则将无法正确构造对象。

    C ++中的多重继承中的构造方法调用 (Constructor call in Multiple Inheritance in C++)

    Its almost the same, all the Base class's constructors are called inside derived class's constructor, in the same order in which they are inherited.

    几乎相同,所有基类的构造函数都在派生类的构造函数内部被调用,其继承顺序相同。

    class A : public B, public C ;

    In this case, first class B constructor will be executed, then class C constructor and then class A constructor.

    在这种情况下,将首先执行B类构造函数,然后是C类构造函数,然后是A类构造函数。

    翻译自: https://www.studytonight.com/cpp/order-of-constructor-call.php

    继承构造函数调用顺序

    展开全文
  • C++多继承构造函数调用顺序

    千次阅读 多人点赞 2011-09-17 21:48:20
     //第三步:又继承B3,在初始化列表里找不到B3(x), 则调用B3里的默认构造函数B3(),打印"constB3 *"  //再按照数据成员定义顺序 :memberB1, memberB2, memberB3  //第四步:在初始化列表里找到memberB1(c),...
    class B1 
    {public:
     B1(int i) 
     {cout<<"consB1"<<i<<endl;}
    };//定义基类B1
    class B2  
    {public:
     B2(int j) 
     {cout<<"consB2"<<j<<endl;}
    };//定义基类B2
    class B3 
    {
    public:
      B3()
      {cout<<"consB3 *"<<endl;}
    };//定义基类B3
    class C: public B2, public B1, public B3 
    {public: 
      C(int a,int b,int c,int d,int e)
       :B1(a),memberB2(d),memberB1(c),B2(b)
      {m=e; cout<<"consC"<<endl;}
    private:
     B1 memberB1;
     B2 memberB2;
     B3 memberB3;
     int m;
    };//继承类C
    void main()
    { C  obj(1,2,3,4,5);  }//主函数


    运行结果:consB2 2 consB1 1 consB3 * consB1 3 consB2 4 consB3 * consC

    //先按照继承顺序:B2,B1,B3 

    //第一步:先继承B2,在初始化列表里找到B2(b),打印"constB22"

     //第二步:再继承B1,在初始化列表里找到B1(a),打印"constB11"

     //第三步:又继承B3,在初始化列表里找不到B3(x), 则调用B3里的默认构造函数B3(),打印"constB3 *" 

    //再按照数据成员定义顺序:memberB1, memberB2, memberB3

     //第四步:在初始化列表里找到memberB1(c),初始化一个B1对象,用c为参数,则调用B1的构造函数,打印"constB13" 

    //第五步:在初始化列表里找到memberB2(d),初始化一个B2对象,用d为参数,则调用B2的构造函数,打印"constB24" 

    //第六步:在初始化列表里找不到memberB3(x),则调用B3里的默认构造函数B3(),打印"constB3 *" 

    //最后完成本对象初始化的剩下部分,也就是C自己的构造函数的函数体:{m=e; cout<<"consC"<<endl;} 

     //第七步:打印"consC"

     回到你的主要问题:为什么会有两次B3*出现? 

    第一次是由于继承了B3,虽然在C的构造函数的初始化列表里你没看到B3(x)或者B3(),但并不代表B3的构造函数没有在发挥作用。事实上,B3被隐性初始化了,因为B3的构造函数没有参数,所以写不写B3()都无所谓,这里恰好省略了。B1,B2则都是显性初始化,因为它们都需要参数。第二次是因为C有数据成员memberB3,又一次,你没有在C的构造函数的初始化列表里看到你希望出现的memberB3(),很显然,这又是一次隐性初始化。B3的构造函数再次被暗中调用。每一次B3的构造函数被调用,都会打印出“consB3 *”。两次被调用,自然打印两次“consB3 *”。

    展开全文
  • C/C++---中多继承构造函数调用顺序

    千次阅读 2018-09-15 19:03:28
     //第三步:又继承B3,在初始化列表里找不到B3(x), 则调用B3里的默认构造函数B3(),打印"constB3 *"  //再按照数据成员定义顺序:memberB1, memberB2, memberB3  //第四步:在初始化列表里找到memberB1(c),...
    class B1 
    {public:
     B1(int i) 
     {cout<<"consB1"<<i<<endl;}
    };//定义基类B1
    class B2  
    {public:
     B2(int j) 
     {cout<<"consB2"<<j<<endl;}
    };//定义基类B2
    class B3 
    {
    public:
      B3()
      {cout<<"consB3 *"<<endl;}
    };//定义基类B3
    class C: public B2, public B1, public B3 
    {public: 
      C(int a,int b,int c,int d,int e)
       :B1(a),memberB2(d),memberB1(c),B2(b)
      {m=e; cout<<"consC"<<endl;}
    private:
     B1 memberB1;
     B2 memberB2;
     B3 memberB3;
     int m;
    };//继承类C
    void main()
    { C  obj(1,2,3,4,5);  }//主函数
    
    运行结果:consB2 2 consB1 1 consB3 * consB1 3 consB2 4 consB3 * consC
    
    //先按照继承顺序:B2,B1,B3 

    //第一步:先继承B2,在初始化列表里找到B2(b),打印"constB22"

     //第二步:再继承B1,在初始化列表里找到B1(a),打印"constB11"

     //第三步:又继承B3,在初始化列表里找不到B3(x), 则调用B3里的默认构造函数B3(),打印"constB3 *" 

    //再按照数据成员定义顺序:memberB1, memberB2, memberB3

     //第四步:在初始化列表里找到memberB1(c),初始化一个B1对象,用c为参数,则调用B1的构造函数,打印"constB13" 

    //第五步:在初始化列表里找到memberB2(d),初始化一个B2对象,用d为参数,则调用B2的构造函数,打印"constB24" 

    //第六步:在初始化列表里找不到memberB3(x),则调用B3里的默认构造函数B3(),打印"constB3 *" 

    //最后完成本对象初始化的剩下部分,也就是C自己的构造函数的函数体:{m=e; cout<<"consC"<<endl;} 

     //第七步:打印"consC"

     回到你的主要问题:为什么会有两次B3*出现? 

    第一次是由于继承了B3,虽然在C的构造函数的初始化列表里你没看到B3(x)或者B3(),但并不代表B3的构造函数没有在发挥作用。事实上,B3被隐性初始化了,因为B3的构造函数没有参数,所以写不写B3()都无所谓,这里恰好省略了。B1,B2则都是显性初始化,因为它们都需要参数。第二次是因为C有数据成员memberB3,又一次,你没有在C的构造函数的初始化列表里看到你希望出现的memberB3(),很显然,这又是一次隐性初始化。B3的构造函数再次被暗中调用。每一次B3的构造函数被调用,都会打印出“consB3 *”。两次被调用,自然打印两次“consB3 *”。

    展开全文
  • 继承与派生,多继承,函数重载,构造函数调用顺序

    遗漏知识点:函数默认参数

    int fun(int a = 1,int b){}
    这里的形参a为函数的默认参数,如果在调用时只传一个实参,则默认a为1.

    类的三大基石:继承,封装,多态 ! ! !

    关于派生类的访问权限:

    继承分为:私有继承,共有继承,保护继承:

    我们几乎不使用 protected 或 private 继承,通常使用 public 继承。当使用不同类型的继承时,遵循以下几个规则:
    1,公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。,
    2,保护继承(protected): 当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。
    3,私有继承(private):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。

    代码演示:

    
    # include<iostream>
    # include<string>
    
    /*基类*/
    class people                  
    {
    public:
        int A;
        void init(int a,int b,int c)           //成员函数
        {
            A = a;
            B = b;
            C = c;                            //基类内部成员函数可以访问所有类成员
        }
    private:
        int B;
    protected:
        int C;
    };
    
    /*公有派生类*/
    class p1:public people
    {
    public:
        int A1;
        void init(int a1,int b1,int c1)
        {
            A = a1;
            //B = b1;                          //报错,公有类型派生类不能访问基类私有成员
            C = c1;
        }
    private:
            int B1;
    protected:
            int C1;
    };
    
    /*私有派生类*/
    class p2:private people
    {
    public:
        int A2;
        void init(int a2,int b2,int c2)
        {
            A = a2;
            //B = b2;                           //报错,私有类型派生类不能访问基类私有成员
            C = c2;
        }
    private:
            int B2;
    protected:
            int C2;
    };
    
    /*保护派生类*/
    class p3:protected people
    {
    public:
        int A3;
        void init(int a3,int b3,int c3)
        {
            A = a3;
            //B = b3;                           /报错,保护类型派生类不能访问基类私有成员
            C = c3;
        }
    private:
            int B3;
    protected:
            int C3;
    };
    
    int main()
    {
        people yu;
        yu.init(1,2,3);
        yu.A;                          //基类对象仅能访问基类的公有成员
        //yu.B;                       //报错  
        //yu.C;                       //报错
    
        p1 yu1;
        yu1.init(1,2,3);
        yu1.A;
        //yu1.B;                     //报错
        //yu1.C;                     //报错,公有继承方式派生类对象仅能访问基类公有成员
    
        p2 yu2;
        yu2.init(1,2,3);
        //yu2.A;                    //报错
        //yu2.B;                    //报错
        //yu2.C;                    //报错,私有继承方式派生类对象不能访问基类任何成员
    
        p3 yu3;
        yu3.init(1,2,3);
        //yu3.A;                 //报错
        //yu3.B;                 //报错
        //yu3.C;                 //报错,保护继承方式派生类对象不能访问基类任何成员
        getchar();
        return 0;
    }

    我们可以根据访问权限总结出不同的访问类型,如下所示:

    访问 (父类) public protected private
    同一个类 yes yes yes
    公有派生类 yes yes no
    公有派生类对象 yes no no
    (下面两个的各个权限是一样的)
    私有派生类 yes yes no
    私有派生类对象 no no no
    保护派生类 yes yes no
    保护派生类对象 no no no

    可总结为两点:

    1,无论以何种类型继承基类,派生类都不能访问基类的私有成员(变量,函数),只能访问保护和公有。
    2,有,且只有,继承类型为公有,的派生类,的对象。才能,且只能,访问基类的公有成员。

    间接访问类私有成员的方式:在类内部公有成员函数里,将私有成员返回。通过在外部调用公有成员函数,便可以实现间接访问类私有成员。

    多继承:

    多继承即一个子类可以有多个父类,它继承了多个父类的特性。
    C++ 类可以从多个类继承成员,语法如下:
    class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
    {
    <派生类类体>
    };

    重载函数:

    用途:

    在一个类中可以定义多个构造函数,以便提供不同的初始化的方法,供用户选用。

    特点:

    1,这些构造函数具有相同的名字,
    2,参数的个数或参数的类型,必须至少有一个不相同不相同。
    3,返回类型,形参标识符不同,并不能构成函数重载合法的依据。
    通过下面的例子可以了解怎样应用构造函数的重载:

    #include <iostream>
    using namespace std;
    
    class printData 
    {
       public:
          void print(int i) {
            cout << "Printing int: " << i << endl;
          }
    
          void print(double  f) {
            cout << "Printing float: " << f << endl;
          }
    
          void print(char* c) {
            cout << "Printing character: " << c << endl;
          }
    };
    
    int main(void)
    {
       printData pd; 
       pd.print(5);
       pd.print(500.263);
       pd.print("Hello C++");
       return 0;
    }
    /*打印结果*/
    /*
    *Printing int: 5
    *Printing float: 500.263)
    *Printing character: c
    */

    关于构造函数的重载的几点说明:

    1,调用构造函数时不必给出实参的构造函数,称为默认构造函数(default constructor)。显然,无参的构造函数属于默认构造函数。一个类只能有一个默认构造函数。
    2,如果在建立对象时选用的是无参构造函数,应注意正确书写定义对象的语句。
    3,尽管在一个类中可以包含多个构造函数,但是对于每一个对象来说,建立对象时只执行其中一个构造函数,并非每个构造函数都被执行。

    在C++里面小数默认为double,而不是float。也就是说想要传入小数实参时, 对应的形参类型必须为double,如果用float编译不通过。

    为什么要调用父类的构造函数?

    构造函数用来初始化类的对象,与父类的其它成员不同,它不能被子类继承(子类可以继承父类所有的成员变量和成员方法,但不继承父类的构造方法)。因此,在创建子类对象时,为了初始化从父类继承来的数据成员,系统需要调用其父类的构造方法。

    C++构造函数调用顺序:

    1、创建派生类的对象,基类的构造函数优先被调用(也优先于派生类里的成员类);

    2、如果类里面有成员类,成员类的构造函数优先被调用;

    3、派生类如果有多个基类,则构造函数的调用顺序是某类在–类派生表–中出现的
      顺序而不是它们在成员初始化表中的顺序;

    4、成员类对象构造函数如果有多个成员类对象则构造函数的调用顺序是对象在类中
      被声明的顺序而不是它们出现在成员初始化表中的顺序;
      
    5、派生类构造函数
      作为一般规则派生类构造函数应该不能直接向一个基类数据成员赋值而是把值传递
      给适当的基类构造函数,否则两个类的实现变成紧耦合的(tightly coupled)将更加难于
      正确地修改或扩展基类的实现。(基类设计者的责任是提供一组适当的基类构造函数)

    代码演示多继承派生类调用父类构造函数的执行顺序:

    #include<iostream>
    #include<string>
    
    using namespace std;
    
    /*基类1*/
    class Base1
    {
    private:
        int a;
    public:
        Base1(int x)               //基类Base1的构造函数
        {
            a=x;
            cout<<"Base1 Constructor !"<<endl;
        }
        int geta() {return a;}
    };
    
    /*基类2*/
    class Base2
    {
    private:
        int b;
    public:
        Base2(int x)                    //基类Base2的构造函数
        {
            b=x;
            cout<<"Base2 Constructor !"<<endl;
        }
            int getb() {return b;}
    };
    
    /*多继承共有类型派生类*/
    class Derived : public Base1,public Base2      //类派生表,此处的继承顺序决定,基类构造函数调用
    {
    private:
        int c;
    public:
        Derived(int x,int y, int z) : Base2(z),Base1(y)    
        //成员初始化表,通过传值调用基类函数实现基类成员变量的初始化
        {
            c=x;
            cout<<"Derived Constructor!"<<endl;
        }
        void show()
        {
            cout<<geta()<<' '<<getb()<<' '<<c<<endl;
        }
    };
    
    /*主函数*/
    void main()
    {
        Derived obj (1,2,3);        //派生类创建对象并初始化成员变量,这三个实参只有一个是给自己用。
        obj.show ();
        getchar();
    }
    
    /*
    程序的输出结果:
    Base1 Constructor !
    Base2 Constructor !
    Derived Constructor!
    2 3 1
    */

    代码说明:

    1,声明一个子类的对象时,首先调用父类的构造函数,
    2,如果一个子类有多个父类时,则按照声明的顺序依次执行父类的构造函数,如class Derived : public Base1,public Base2 你先声明Base1,后声明Base2,所以先调用Base1后调用Base2的构造函数,而与 Base2(z),Base1(y)的顺序无关。

    展开全文
  • 1、首先调用父类的无参构造函数(这个构造han)
  • 调用派生类的构造函数之前先调用基类的构造函数,析构函数则相反。因为派生类需要用到基类的成员,所以必须先有基类,再有派生类。 C++语法规定: 如果类没有显示定义构造函数,则编译器提供一个默认构造函数...
  • 构造函数调用顺序

    千次阅读 2017-09-19 14:46:23
    构造函数调用顺序: class B1 { public: B1(int i){cout;} }; class B2 { public: B2(int j){cout;} }; class B3 { public: B3(){cout
  • C++继承构造函数调用顺序

    千次阅读 2013-04-14 21:37:06
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 简单单继承 class Y {...} ...构造函数调用顺序是下面的顺序:
  • 构造函数调用顺序从上面的分析中可以看出,基类构造函数总是被优先调用,这说明创建派生类对象时,会先调用基类构造函数,再调用派生类构造函数,如果继承关系有好几层的话,例如: A --> B --> C 那么...
  • C++构造函数调用顺序

    千次阅读 2019-06-24 09:49:26
    C++构造函数按下列顺序调用: (1)任何虚拟基类的构造函数按照它们被继承顺序构造; (2)任何非虚拟基类的构造函数按照它们被继承顺序构造; (3)任何成员对象的构造函数按照它们声明的顺序调用; (4)类自己...
  • 关于父类与子类的构造函数调用顺序
  • 析构函数的调用顺序构造函数恰好相反。 要注意的一点是:在该例中,类B通过类D和类A间接继承了两次类C,此时的类B中含有两份类C的拷贝,若C中含有数据成员,则可能会导致二义性( ambiguous ),这样的多重...
  • C++中类的构造函数调用顺序

    千次阅读 2015-09-23 17:02:28
    当建立一个对象时,首先调用基类的构造函数,然后调用下一个派生类的构造函数,依次类推,直至到达派生类次数最多的派生次数最多的类的构造函数为止。简而言之,对象是由“底层向上”开始构造的。因为,构造函数一...
  • 前言: Hello,全世界早上好啊,哈哈,9月你好,2015年9月的第一天,也是...扯远了,往下的日子里,更要好好努力,今天以一道面试题为说起,理解或者说感受类中关于构造函数调用顺序问题: Let’s show the code
  • 派生类的构造函数在初始化时会先寻找虚继承自间接基类的直接基类,先...构造函数调用顺序为:M(),A(),M(),B(),C(). 构造函数调用顺序为:M(),M(),A(),B(),C(). 构造函数调用顺序为:M(),N(),A(),B(),C().
  • 一、派生类对象中基类构造函数和派生类中构造函数调用顺序(WIN7 64位 VS2012) (1)、先执行派生类的构造函数还是先执行基类中的构造函数? 利用下面这段代码进行打印测试 #include using namespace std; // 基类 ...
  • C++中若某类a从基类b、虚基类c派生而来,且该类中具有对象成员d,则在构造该类的对象时执行...2.如果该类有其他基类,按照他们在继承声明列表中出现的顺序分别执行构造函数,但是不再执行它们的虚基类的构造函数。 3.
  • 继承时的构造函数调用顺序

    千次阅读 2014-01-17 00:03:24
    调用顺序是:虚基类——直接基类——子对象——派生类 ...首先说明,构造函数的调用顺序,跟D中的构造函数调用个类的成员函数的顺序无关 因为B和C都是虚继承自A,所以首先调用都在A的构造函数,然后
  • 当派生类继承了基类,并且类中有基类对象作为成员变量时,构造函数调用顺序是怎样的呢? 看下面的程序: 派生类继承了两个基类A和B,主函数里定义了一个派生类对象: #include using namespace std; class A...
  • Java构造函数调用顺序

    千次阅读 2015-04-27 21:46:40
    使用super调用父类构造器的语句必须是子类构造器的第一条语句,如果子类构造器没有显式地调用父类的构造器,则将自动调用父类的默认(没有参数)的构造器。如果父类没有不带参数的构造器,并且在子类的构造器中又...
  • 今天在博客上看到一段解释继承中析构函数和构造函数调用顺序描述,觉得讲的不错,分享给大家,下面的代码是自己的验证。  首先说说构造函数,大家都知道构造函数里就可以调用成员变量,而继承中子类是把基类的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 177,689
精华内容 71,075
关键字:

继承构造函数调用顺序