精华内容
下载资源
问答
  • 构造函数和析构函数的执行顺序 我们在创建一个类的对象的时候,编译器会自动调用构造函数。由于这个类可能继承自某些类并且里面还有一些其他类的对象,那么他们的构造函数和析构函数的调用顺序是怎样的呢? LET’S ...

    构造函数和析构函数的执行顺序

    我们在创建一个类的对象的时候,编译器会自动调用构造函数。由于这个类可能继承自某些类并且里面还有一些其他类的对象,那么他们的构造函数和析构函数的调用顺序是怎样的呢?
    LET’S HAVE A TRY!

    试验源码:

    #include <iostream>
    using namespace std;
    class O{
    public:
    	O(){
    		cout << "Constructor O" << endl;
    	}
    	~O(){
    		cout << "Deconstructof O" << endl;
    	}
    };
    
    class A:O{
    public:
    	A(){
    		cout << "Constructor A" << endl;
    	}
    	~A(){
    		cout << "Deconstructof A" << endl;
    	}
    };
    
    class B{
    public:
    	B(){
    		cout << "Constructor B" << endl;
    	}
    	~B(){
    		cout << "Deconstructof B" << endl;
    	}
    };
    
    class C{
    public:
    	C(){
    		cout << "Constructor C" << endl;
    	}
    	~C(){
    		cout << "Deconstructof C" << endl;
    	}
    };
    
    class D{
    public:
    	D(){
    		cout << "Constructor D" << endl;
    	}
    	~D(){
    		cout << "Deconstructof D" << endl;
    	}
    };
    
    class E{
    public:
    	E(){
    		cout << "Constructor E" << endl;
    	}
    	~E(){
    		cout << "Deconstructof E" << endl;
    	}
    };
    
    class Test : E,D{
    	B b;
    	A a;
    public:
    	Test(){
    		cout << "Constructor Test" << endl;
    	}
    	~Test(){
    		cout << "Deconstructor Test" << endl;
    	}
    };
    
    int main(){
    	Test *t = new Test;
    	delete t;
    	system("pause");
    	return 0;
    }
    
    

    在这里插入图片描述
    一目了然!
    构造函数的执行顺序:

    1. 基类的构造函数
    2. 成员类的构造函数
    3. 派生类的构造函数

    注意:如果有多个基类,则按照继承的顺序进行调用(对应此例中E,D)
    如果有多个成员类,则按照成员类在当前类中声明的顺序(对应此例中A,B)

    析构函数的执行顺序:
    与构造函数的执行顺序完全相反。

    1. 派生类的析构函数
    2. 成员类的析构函数
    3. 基类的析构函数
    展开全文
  • 构造函数和析构函数的调用顺序

    千次阅读 2019-09-03 15:47:29
    目录构造函数和析构函数构造函数复制构造函数析构函数构造函数与析构函数的调用顺序单继承多继承 构造函数和析构函数 构造函数 构造函数是特殊的成员函数,与类同名,没有返回类型,而且允许重载。如果没有为类显式...

    构造函数和析构函数

    构造函数

    构造函数是特殊的成员函数,与类同名,没有返回类型,而且允许重载。如果没有为类显式定义任何构造函数,编译器将自动为类生成默认构造函数(不带任何参数)。

    复制构造函数

    复制构造函数、赋值操作符合析构函数总称为复制控制。复制构造函数只有单个形参,而且该形参是对本类类型的引用(通常用const修饰)。复制构造函数常用于:
    1)根据另一个同类型的对象初始化一个对象

    string a("123456");
    string b(a);
    

    2)在顺序容器的元素初始化和类类型数组元素初始化时,也会默认使用复制构造函数。
    3)复制一个对象,将它作为实参传给一个函数或从函数返回时复制一个对象。也就是说,如果函数的形参或返回值是一个类的话,将会调用复制构造函数进行复制。

    class Myclass
    {
    public:
    	Myclass(int n) { number = n; }
    	Myclass(const Myclass &other)
    	{
    		number = other.number;
    		cout << "copy";
    	}
    private:
    	int number;
    };
    
    Myclass fun(Myclass p)
    {
    	Myclass temp(p);
    	return temp;
    }
    
    
    void main()
    {
    
    	Myclass a(10);
    	Myclass b(a);
    	Myclass c = fun(b);
    	system("pause");
    }
    

    最后会输出四个copy,第一次调用在b(a),第二次在fun传参,调用复制构造函数,等价于p(b),第三次temp§,第四次返回值,等价于c(temp)。

    析构函数

    析构函数用于释放对象在生命期内获取的资源,不管类是否定义了自己的析构函数,编译器都自动执行类中非static数据成员的析构函数。需要注意的是,构造函数不能被定义成虚函数,但是析构函数可以。一般来说,如果类中定义了虚函数,那么析构函数也应该被定义成虚函数。虚析构函数和析构函数的差别在于,如果用new运算符建立的派生类的临时对象,对指向基类的指针指向这个临时对象当用delete运算符撤销对象时,系统执行的是基类的析构函数,而不是派生类的析构函数,不能彻底的“清理现场”。解决的方法是将基类及派生类的析构函数设为虚函数,这时无论基类指针指向哪个派生类对象,系统会采用动态关联,调用相应的析构函数对对象进行清理。

    class A {
    public:
    	A() { cout << "A"; }
    	~A() { cout << "~A"; }
    };
    class B: public A{
    public:
    	B() { cout << "B"; }
    	~B() { cout << "~B"; }
    };
    
    void f()
    {
    	A *a = new B;
    	delete a;
    	getchar();
    }
    int  main()
    {
    	f();
    	system("pause");
    	return 0;
    }
    

    此时输出为AB~A,会出现释放不彻底的问题
    如果将其均改为虚析构函数(实际这里改A就行),输出就为AB~B ~A

    构造函数与析构函数的调用顺序

    单继承

    派生时,构造函数和析构函数是不能继承的,因此必须在派生类中重新定义构造函数和析构函数。创建派生类时,先调用基类的构造函数完成基类成员的初始化,而后对派生类新增的成员初始化。析构时顺序相反。

    class A {
    public:
    	A() { cout << "A"; }
    	A(const A &a) { cout << "copy"; }
    	virtual ~A() { cout << "~A"; }
    
    };
    class B: public A{
    public:
    	B(A &a):_a(a) { cout << "B"; }
    	virtual ~B() { cout << "~B"; }
    private:
    	A _a;
    };
    
    void f()
    {
    	A(a);
    	B b(a);
    }
    int  main()
    {
    	f();
    	system("pause");
    	return 0;
    }
    

    输出为
    A A copy B ~B ~A ~A ~A
    构造B时,首先调用基类的构造函数,完成初始化,之后调用B的构造函数,此处为复制构造,复制构造函数也会构造一个A对象,复制构造结束后才会构造一个派生类对象。析构时按相反的顺序析构,注意无论是默认构造函数,复制构造函数或者其他重载的构造函数创造的对象,都会被析构。
    严格来说,派生类函数的调用顺序为
    1)完成对象所占整块内存的开辟,由系统调用构造函数自动完成
    2)调用基类的构造函数完成基类成员的初始化
    3)派生类中含对象成员,const成员和引用成员的初始化
    4)派生类构造函数

    多继承

    多继承时,按照基类构造函数在类派生列表中的出现次序调用

    class A
    {
    public:
    	A() { cout << "A Constructor..." << endl; }
    	~A() { cout << "A Destructor..." << endl; }
    };
    
    class B
    {
    public:
    	B() { cout << "B Constructor..." << endl; }
    	~B() { cout << "B Destructor..." << endl; }
    };
    
    class C :public A, public B
    {
    public:
    	C() { cout << "C Constructor..." << endl; }
    	~C() { cout << "C Destructor..." << endl; }
    };
    
    
    class D : public C
    {
    public:
    	D() { cout << "D Donstructor..." << endl; }
    	~D() { cout << "D Destructor..." << endl; }
    };
    
    void f()
    {
    	D d;
    }
    
    void main()
    {
    	f();
    	system("pause");
    }
    

    在这里插入图片描述
    需要注意的是,如果多继承中存在虚继承,那么优先调用虚继承的构造函数。

    展开全文
  • C++构造函数和析构函数的调用顺序

    万次阅读 2018-09-04 00:05:03
    1、构造函数的调用顺序  基类构造函数、对象成员构造函数、派生类本身的构造函数  2、析构函数的调用顺序 派生类本身的析构函数、对象成员析构函数、基类析构函数(与构造顺序正好相反)  3、特例  局部...

    1、构造函数的调用顺序 

    基类构造函数、对象成员构造函数、派生类本身的构造函数  

    2、析构函数的调用顺序

    派生类本身的析构函数、对象成员析构函数、基类析构函数(与构造顺序正好相反) 

    3、特例 

    局部对象,在退出程序块时析构

    静态对象,在定义所在文件结束时析构

    全局对象,在程序结束时析构 

    继承对象,先析构派生类,再析构父类 

    对象成员,先析构类对象,再析构对象成员

    #include "stdafx.h"
    #include <iostream>
    using namespace std;
    
    class  Clock
    {
    public:
    	Clock()
    	{
    		cout << "clock的构造函数" << ",";
    	}
    	~Clock()
    	{
    		cout << "clock的析构函数" << ",";
    	}
    };
    
    class Date
    {
    public:
    	Date()
    	{
    		cout << "date的构造函数" << ",";
    	}
    	~Date()
    	{
    		cout << "date的析构函数" << ",";
    	}
    };
    
    
    void main()
    {
        Clock c;
    	Date d;
    	system("pause");
    }

    在使用构造函数和析构函数时,需要特别注意对它们的调用时间和调用顺序。在一般情况下,调用析构函数的次序正好与调用构造函数的次序相反:最先被调用的构造函数,其对应的(同一对象中的)析构函数最后被调用,而最后被调用的构造函数,其对应的析构函数最先被调用。
    可以简记为:先构造的后析构,后构造的先析构,它相当于一个栈,先进后出

    展开全文
  • 1.类的构成 class 类名 { public: 公有数据成员; 公有成员函数; protected: ...不能在类中给数据成员赋值,需要在构造函数中赋值。 2.成员函数的声明 在类中给出函数声明: 返回类型 成员函数(参数列表)

    1.类的构成

    class  类名 {
    public:
      公有数据成员;
      公有成员函数;
    protected:
      保护数据成员;
      保护成员函数;
    private:
      私有数据成员;
      私有成员函数;
     };
    

    private只能本类的成员函数访问

    protected可以由本类或者派生类访问

    public是任意函数能访问

    private出现在程序的开始时,关键词可以省略。

    不能在类中给数据成员赋值,需要在构造函数中赋值。

    2.成员函数的声明

    在类中给出函数声明:

    返回类型  成员函数(参数列表);
    

    在类外给出函数定义:

    返回类型  类名∷成员函数名(参数表)
      {
           // 函数体
      }
    

    内联函数:函数体放在类中。

    外联函数:函数头放在类中,定义在类外。

    内联函数性能优于外联函数,在外联函数前面加上inline可以将外联函数转化为内联函数。

    一般较短的定义为内联函数比较合适,较长的定义为一般函数。

    3.对象的定义和使用

    声明对象

    可以在声明类的同时定义,也可以在声明后定义。

    class  Coord { 
        public:
            void setCoord(int,int);
            int getx();
            int gety();
        private:
            int  x,y;
        }   op1,op2; 
    
    class  Coord { 
         //…
      }; 
         // …
     main()
     {
       Coord  op1,op2;
         // …
      }
    

    访问对象的方法

    对象名.数据成员名

    对象名.成员函数名

    其实是一种缩写:

    对象名.类名::成员名

    如果定义指向对象的指针,使用->访问成员

    对象赋值

    相同类型变量可以互相赋值,赋值方法为逐位拷贝。

    如果类中存在指针,可能会出现错误。

    4.构造函数与析构函数

    构造函数作用

    初始化成员变量,

    没有返回类型,

    可以没有参数

    必须和类同名,不需要用户调用。

    class 类名
    { public:
    	类名(形参表);		//构造函数的原型
    	//类的其它成员
    };
    类名::类名(形参表)	//构造函数的实现
    {
    	//函数体
    } 
    

    构造函数初始化参数的方式

    在函数体内赋值

    或者使用初始化列表的方式

    类名::构造函数名(参数表):(成员初始化表)
    {
        // 构造函数体
    }
    

    初始成员列表的形式为:

    数据成员名1(初始值1),数据成员名2(初始值2),…… 
    

    拷贝构造函数

    使用一个已经存在的对象初始化新对象

    如果使用等号赋值,系统自动调用拷贝构造函数。

    拷贝构造函数也是构造函数,只有一个参数,是同类对象的引用。

    可以对拷贝构造函数进行自定义:

    class 类名
    {  public :
           类名(形参);//构造函数
           类名(类名 &对象名);//拷贝构造函数
               ...
    };
    类名:: 类名(类名 &对象名)//拷贝构造函数的实现
    {    函数体    }
    

    拷贝构造函数的使用:

    Coord p2(p1);    // 用对象p1初始化对象p2, 
    Coord p3=p1;    // 用对象p1初始化对象p3, 
    

    缺省拷贝构造函数:如果没有定义拷贝构造函数,C++自动使用逐个成员拷贝的方式。

    浅拷贝:默认拷贝函数的方式,逐一拷贝数据成员。如果数据成员出现指针会产生错误。

    深拷贝:自定义拷贝,将指针所指的内存进行拷贝

    类组合构造函数

    类组合指的是类的成员是一个类的对象。

    类组合构造函数必须对本类中的基本类型成员数据赋值,也要对对象成员初始化。

    类名::类名(对象成员所需的形参,本类成员形参)
           :对象1(参数),对象2(参数)......
    {  本类初始化  }
    

    先调用内嵌对象的构造函数,然后调用本类的构造函数。

    析构函数

    与类名称相同,多一个~,不能被重载,无函数值,没有参数,没有返回值

    生命周期结束时,系统自动调用。

    调用顺序

    构造函数1->构造函数2->构造函数3->结构函数3->解构函数2->解构函数1

    向前引用声明

    如果需要在类声明之前引用该类,需要向前引用声明。

    要求在完整声明其之前不能声明该类的对象。可以声明该类的指针。但是不能使用该类的方法或者成员变量。

    class B;  //前向引用声明
    class A
    {  public:
          void f(B b);
    };
    class B
    {  public:
          void g(A a);
    };
    
    展开全文
  • 构造函数:在类实例化对象时自动执行,对类中的数据进行初始...调用构造函数和析构函数的顺序:先构造的后析构,后构造的先折构。它相当于一个栈,先进后出。#include#includeusing namespace std;class Student{pub...
  • C++遵循如下的创建顺序:(1)如果某个类具体基类,执行基类的默认构造函数。(2)类的非静态数据成员,按照声明的顺序创建。(3)执行该类的构造函数。即构造类时,会先构造其父类,然后创建类成员,最后调用本身的构造...
  • 继承时,构造函数和析构函数的调用顺序 保证你们一篇看懂,不懂得可以留言!!!一定给你们讲明白! 先调用父类的构造函数,再初始化成员,最后调用自己的构造函数 先调用自己的析构函数,再析构成员,最后调用父类...
  • C/C++——构造函数和析构函数

    千次阅读 2015-11-21 12:33:09
    本文对类的构造函数和析构函数进行总结,主要包括了构造函数的初始化、重载、使用参数和默认参数,拷贝构造函数和析构函数。
  • 多重继承的问题:多个类B,C,…继承同一个类A导致如果X继承了B,C,…那么在X中将还有多个A中成员的拷贝,如果想要访问A中的成员如果不加名字空间将会导致二义性,这种拷贝大多是没有实际意义的,为了避免这种空间浪费...
  • c++构造函数和析构函数的调用顺序

    千次阅读 2019-04-22 14:33:45
    在使用构造函数和析构函数时,需要特别注意对他们的调用时间和调用顺序,在一般情况下,调用析构函数的次序正好与调用构造函数的次序相反,最先被调用的构造函数,其对应(同一对象中的)析构函数最后被调用,而最后...
  • 在C++的类继承中,构造函数不能被继承(C11中可以被继承,但仅仅是写起来方便,不是真正的继承) 建立对象时,首先调用基类的构造函数,然后在调用下一个派生类的构造函数,依次类推; 析构对象时,其顺序正好与...
  • 最近自考C++刷题的时候快被构造函数和析构函数搞得疯掉了,现在特意写一篇博客来记录自己的收获! 在我们创建新的对象的时候,都要执行某一个类中的构造函数,而当构造函数中分配了资源之后,当我们销毁一个对象...
  • 构造函数(constructor) C++编程中有一些规范要注意。 1. 头文件(Header)中的防卫式声明 在头文件complex.h中,为了避免已经存在该名字的头文件,可以进行防卫式的声明,形式如下: #ifndef __COMPLEX__ #...
  • C++ 派生类的析构函数的调用顺序为:A) 基类、派生类对象成员类的析构函数  B) 派生类、对象成员类基类的析构函数  C) 对象成员类、派生类基类的析构函数 ...关于派生类构造函数与基类构造函数的调用
  • 下面示例就是说明多重继承析构函数和构造函数的执行顺序: #include <iostream> using namespace std; class A { public: A(int i) { cout << "父类A构造函数被调用:" << i<<endl; } ...
  • 基类的构造函数(如果有多个基类,按照基类的声明顺序来构造,声明顺序也就是class C:冒号后面这个顺序);该派生类的成员变量的声明顺序;该派生类自身的构造函数 派生类析构顺序:其实就是构造的逆序。 #include...
  • 通常情况下: 当创建派生类对象时: 基类的构造函数——>派生类的构造函数;...1.派生类的构造函数和析构函数的调用顺序 (1) 输出的是:基类的构造函数 基类的构造函数 派生类的构造函数 输出...
  • 构造函数和析构函数

    万次阅读 2018-05-30 11:24:57
    通过C++ Primer重新回顾构造函数和析构函数,发现真的好多都忘了… 构造函数 类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。 构造函数的名称与类的名称是完全相同的,并且不会返回...
  • 一、构造函数的执行顺序: 二、析构函数的执行顺序 三、用一段代码来说明 #include <iostream> using namespace std; class B1 { public: B1(int i=100){ cout<<"constructing B1 "<<i...
  • (1)如果某个类具体基类,执行基类的默认构造函数。 (2)类的非静态数据成员,按照声明的顺序创建。 (3)执行该类的构造函数。 即构造类时,会先构造其父类,然后创建类成员,最后调用本身的构造函数。 ...
  • C++ 析构函数 构造器 虚拟函数
  • Virtual virtual在英文中表示“虚”、“虚拟”的含义。...这里“重写”的要求是函数的特征标(包括参数的数目、类型和顺序)以及返回值都必须与基类中的函数一致。如下所示: class base { public: void t
  • C++中的解决方案,构造函数和析构函数,这两个函数将会被编译器自动调用,完成对象初始化和对象清理工作 不管有没有我们有没有提供初始化操作和清理操作,编译器也会增加默认的操作,只是这个默认初始化操作不会做...
  • 构造顺序与析构顺序

    千次阅读 2019-03-19 10:33:25
    1. 调用基类构造函数,调用顺序按照它们被继承时声明的顺序(从左到右); 2. 调用内嵌成员对象的构造函数,调用顺序按照它们在类中声明的顺序; 3. 派生类自己构造函数体中的内容。 派生类析构函数执行的次序: ...
  • 在面向对象编程语言中,一个类的构造函数和析构函数是两个比较特殊的成员函数,它们主要用于对象的创建和销毁,和对象的生命周期息息相关,因此它们有着特殊的含义。编译器对待它们和其它普通的成员函数不一样,在...
  • 构造函数与析构函数及调用顺序构造函数定义特点析构函数定义特点构造函数与析构函数的执行顺序例题 构造函数 定义 构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据...
  • 构造函数–初始化 析构函数–清理 编译器自动调用,创建对象时,编译器自动调用构造函数,对象销毁时,编译器自动调用析构函数 默认情况下,C++会给一个类默认添加三个函数: 默认构造函数,函数体为空 默认析构...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 26,243
精华内容 10,497
关键字:

c构造函数和析构顺序