精华内容
下载资源
问答
  • c++ 构造函数详解

    万次阅读 多人点赞 2019-05-31 17:20:58
    c++构造函数详解。(构造函数的分类、拷贝构造函数)

    c++ 构造函数详解

    构造函数是干什么的

    • 该类对象被创建的时候,编译系统对象分配内存空间,并自动调用该构造函数,由构造函数完成成员的初始化工作,故:构造函数的作用:初始化对象的数据成员

    构造函数的分类

    • 无参构造函数
    • 带默认值的构造函数
    • 有参(无默认值)的构造函数
    • 复制构造函数(拷贝构造函数)
      • 一种特殊的构造函数,当对象之间复制时会自动调用拷贝构造函数
      • 若类中没有显示定义拷贝构造函数,则系统会自动生成默认拷贝构造函数
    	#include <iostream>
    	using namespace std;
    	
    	class Coordinate
    	{
    	public:
    		// 无参构造函数
    		// 如果创建一个类你没有写任何构造函数,则系统自动生成默认的构造函数,函数为空,什么都不干
    		// 如果自己显示定义了一个构造函数,则不会调用系统的构造函数
    		Coordinate()
    		{
    			c_x = 0;
    			c_y = 0;
    		}     
    	
    		// 一般构造函数
    		Coordinate(double x, double y):c_x(x), c_y(y){}   //列表初始化
    		// 一般构造函数可以有多个,创建对象时根据传入的参数不同调用不同的构造函数
    	
    		Coordinate(const Coordinate& c)
    		{
    			// 复制对象c中的数据成员
    			c_x = c.c_x;
    			c_y = c.c_y;
    		}
    	
    		// 等号运算符重载
    		Coordinate& operator= (const Coordinate& rhs)
    		{
    			// 首先检测等号右边的是否就是等号左边的对象本身,如果是,直接返回即可
    			if(this == &rhs)
    				return* this;
    			// 复制等号右边的成员到左边的对象中
    			this->c_x = rhs.c_x;
    			this->c_y = rhs.c_y;
    			return* this;
    		}
    	
    		double get_x()
    		{
    			return c_x;
    		}
    	
    		double get_y()
    		{
    			return c_y;
    		}
    	
    	private:
    		double c_x;
    		double c_y;
    	};
    	
    	int main()
    	{
    		// 调用无参构造函数,c1 = 0,c2 = 0
    		Coordinate c1, c2;
    		// 调用一般构造函数,调用显示定义构造函数
    		Coordinate c3(1.0, 2.0);
    		c1 = c3;    //将c3的值赋值给c1,调用"="重载
    		Coordinate c5(c2);
    		Coordinate c4 = c2;    // 调用浅拷贝函数,参数为c2
    		cout<<"c1 = "<<"("<<c1.get_x()<<", "<<c1.get_y()<<")"<<endl
    			<<"c2 = "<<"("<<c2.get_x()<<", "<<c2.get_y()<<")"<<endl
    			<<"c3 = "<<"("<<c3.get_x()<<", "<<c3.get_y()<<")"<<endl
    			<<"c4 = "<<"("<<c4.get_x()<<", "<<c4.get_y()<<")"<<endl
    			<<"c5 = "<<"("<<c5.get_x()<<", "<<c5.get_y()<<")"<<endl;
    		return 0;
    	}
    
    	c1 = (1, 2)
    	c2 = (0, 0)
    	c3 = (1, 2)
    	c4 = (0, 0)
    	c5 = (0, 0)
    	请按任意键继续. . .
    

    拷贝构造函数

    • 拷贝构造函数是一种特殊的构造函数,具有单个形参,该形参(常用const修饰)是对该类型的引用。当定义一个新对象并用同一类型的对象都它进行初始化时,将显示使用拷贝构造函数,当该类型的对象传递给函数返回该类型的对象时,将隐式调用拷贝构造函数
    • 当类中有一个数据成员是指针时,或者有成员表示在构造函数中分配的其他资源,必须显示定义拷贝构造函数
    • 构造函数的使用情况
      • 一个对象以值传递的方式传入函数体
      • 一个对象以值传递的方式从函数体返回
      • 一个对象需要通过另一个对象进行初始化
    	#include <iostream>
    	using namespace std;
    	
    	class Test
    	{
    	public:
    		// 构造函数
    		Test(int a):t_a(a){
    		cout<<"creat: "<<t_a<<endl;
    		}
    	
    		// 拷贝构造函数
    		Test(const Test& T)
    		{
    			t_a = T.t_a;
    			cout<<"copy"<<endl;
    		}
    	
    		// 析构函数
    		~Test()
    		{
    			cout<<"delete: "<<t_a<<endl;
    		}
    	
    		// 显示函数
    		void show()
    		{
    			cout<<t_a<<endl; 
    		}
    	
    	private:
    		int t_a;
    	};
    	
    	// 全局函数,传入的是对象
    	void fun(Test C)
    	{
    		cout<<"test"<<endl;
    	}
    	
    	int main()
    	{
    		Test t(1);
    		// 函数中传入对象
    		fun(t);
    		return 0;
    	}
    
    	creat: 1
    	copy
    	test
    	delete: 1
    	delete: 1
    	请按任意键继续. . .
    

    浅拷贝与深拷贝

    • 浅拷贝
      • 所谓浅拷贝,指的是在对象复制时,只对对象中的数据成员进行简单的赋值,默认拷贝构造函数执行的也是浅拷贝。也就是增加了一个指针,指向原来已经存在的内存。 正常情况下,“浅拷贝”已经能很好的工作,但是一旦对象存在动态成员,浅拷贝就会出问题。让我们考虑下面一段代码:
    	#include <iostream>
    	#include <assert.h>    
    	using namespace std;
    	
    	class Test
    	{
    	public:
    		Test(){
    			p = new int(10);
    		}
    	
    		~Test(){
    			assert(p != NULL);     // assert()作用是如果他的条件返回错误,则终止程序执行 
    			delete p;
    		}
    	private:
    		int x;
    		int y;
    		int* p;
    	};
    	
    	int main()
    	{
    		Test t1;
    		Test t2(t1);    // 调用默认拷贝构造函数
    		return 0;
    	}
    

    上述程序崩溃。在使用t1复制t2时,进行的是浅拷贝,只是将成员的值进行赋值。此时,t1.p = t2.p, 即两个指针指向了堆里的同一个空间。这样,析构函数会被调用两次,这就是错误出现的原因。此问题的解决方法是“深拷贝”。

    • 深拷贝
      • 深拷贝就是对于对象中的动态成员,并不只是简单的赋值,而是重新分配空间,即资源重新分配。上述代码处理如下:
    	#include <iostream>
    	#include <assert.h>    
    	using namespace std;
    	
    	class Test
    	{
    	public:
    		Test(){
    			x = 0;
    			y = 0;
    			p = new int(10);
    		}
    	
    		Test(const Test& t)
    		{
    			x = t.x;
    			y = t.y;
    			p = new int(10);
    			*p = *(t.p);
    		}
    	
    		~Test(){
    			assert(p != NULL);     // assert()作用是如果他的条件返回错误,则终止程序执行 
    			delete p;
    		}
    	
    		int get_x(){return x;}
    		int get_y(){return y;}
    	private:
    		int x;
    		int y;
    		int* p;
    	};
    	
    	int main()
    	{
    		Test t1;
    		Test t2(t1);    // 调用默认拷贝构造函数
    		cout<<"("<<t1.get_x()<<", "<<t1.get_y()<<")"<<endl
    			<<"("<<t2.get_x()<<", "<<t2.get_y()<<")"<<endl;
    		return 0;
    	}
    
    (0, 0)
    (0, 0)
    请按任意键继续. . .
    

    此时t1与t2的p各自指向一段内存空间,但他们指向的内容相同,这就是“深拷贝”。

    展开全文
  • C++ 构造函数

    千次阅读 多人点赞 2017-04-13 22:36:41
    C++ 析构函数

    1. 定义

        与类同名无返回值类型的成员函数。

        析构函数是对象创建的一部分,在创建对象时,会被自动调用;创建对象后,析构函数就不能再被调用

        默认析构函数:不带参数,或者所有参数都有默认值的的析构函数,析构函数可以重载。

        类的析构函数一般是公开的,但是有时也把析构函数声明为私有的(如单例模式中就把析构函数声明为私有的),其作用是限制创建该类对象的范围。

    2. 调用

        根据参数进行重载,决定调用哪个析构函数。

    3. 成员初始化表

        对于常量数据成员和引用数据成员(某些静态成员除外),不能在声明它们时进行初始化,也不能采用赋值操作对它们初始化

        

    class A
    {
        int x;
        const int y=1;//Error
        int &z=x;//Error
      public:
        A()
        {
            x=0;//OK
            y=1;//Error,y是常量成员,其值不能改变
        }
    }

        它们的初始化要在成员初始化表中进行。

        

    class A
    {
        int x;
        const int y;
        int& z;
      public:
        A(): z(x),y(1)
        {
             x=0;
        }
    }

        或者

        

    class A
    {
        int x;
        const int y;
        int& z;
      public:
        A(): x(0),z(x),y(1)
        {
        }
    }


        成员初始化表的次序不决定它们的初始化次序,它们的初始化次序由它们在类中的定义的次序决定

        如果类中含有常量数据成员或引用数据成员,一定要定义带有成员初始化表的构造函数,否则编译程序生成的默认构造函数是没有成员初始化表的,这样的类是不能创建对象的。

        在创建包含成员对象的对象时,首先调用本身类的构造函数,在进入本身类的析构函数之前,将会去调用成员对象类的构造函数,然后再执行本身构造函数的函数体(在继承中,要先调用基类的构造函数,再调用成员对象类的构造函数,最后执行自己的函数体)。即使成员对象初始化表为空,只要类中有成员对象,编译程序就会生成对成员对象构造函数的调用指令,只不过它调用的默认构造函数。

    展开全文
  • C++构造函数

    千次阅读 2019-06-20 09:01:34
    (5) 如果用户自己没有定义构造函数,则C++系统会自动生成一个构造函数,只是这个构造函数的函数体是空的,也没有参数,不执行初始化操作 【例】定义一个Clock时钟类 class Clock {public: Clock( ) //定义...
    • 对象的初始化
      在建立一个对象时,常常需要作某些初始化的工作,例如对数据成员赋初值。如果一个数据成员未被赋值,则它的值是不可预知的,因为在系统为它分配内存时,保留了这些存储单元的原状,这就成为了这些数据成员的初始值。这种状况显然是与人们的要求不相符的,对象是一个实体,它反映了客观事物的属性(例如时钟的时、分、秒的值),是应该有确定的值的。
      注意: 类的数据成员是不能在声明类时初始化的。
    • 构造函数的作用
      为了解决这个问题,C++提供了构造函数(constructor)来处理对象的初始化。构造函数是一种特殊的成员函数,与其他成员函数不同,不需要用户来调用它,而是在建立对象时自动执行。构造函数的名字必须与类名同名,而不能由用户任意命名,以便编译系统能识别它并把它作为构造函数处理。它不具有任何类型,不返回任何值。构造函数的功能是由用户定义的,用户根据初始化的要求设计函数体和函数参数。
    • 构造函数有以下特点:
      1)构造函数是类的一个成员函数,但有其特殊性;
      2)构造函数的函数名与类名相同,它不能有返回值,即使是void也不行。
      3)构造函数可以有参数,也可以没有参数,换句话说,构造函数可以重载;
      4)程序一般不直接调用构造函数,在创建对象时会自动调用构造函数,以完成对象的初始化工作。
      说明:
      (1) 在类对象进入其作用域时调用构造函数。
      (2) 构造函数没有返回值,因此也不需要在定义构造函数时声明类型,这是它和一般函数的一个重要的不同之点。
      (3) 构造函数不需用户调用,也不能被用户调用。
      (4) 在构造函数的函数体中不仅可以对数据成员赋初值,而且可以包含其他语句。但是一般不提倡在构造函数中加入与初始化无关的内容,以保持程序的清晰。
      (5) 如果用户自己没有定义构造函数,则C++系统会自动生成一个构造函数,只是这个构造函数的函数体是空的,也没有参数,不执行初始化操作

    【例】定义一个Clock时钟类

    class Clock
      {public:
          Clock( )                 //定义构造成员函数,函数名与类名相同
         { hour=0;            //利用构造函数对对象中的数据成员赋初值
            minute=0;
            sec=0;
         }
    void set_time( );           //函数声明
    void show_time( );          //函数声明
    private:
    int hour;                  //私有数据成员
    int minute;
    int sec;
    };
    void Time∷set_time( )        //定义成员函数,向数据成员赋值
    {cin>>hour;
    cin>>minute;
    cin>>sec;
    }
    void Time∷show_time( )         //定义成员函数,输出数据成员的值
    {
     cout<<hour<<″:″<<minute<<″:″<<sec<<endl;
    }
    

    带参数的构造函数
    可以采用带参数的构造函数,在调用不同对象的构造函数时,从外面将不同的数据传递给构造函数,以实现不同的初始化。构造函数首部的一般格式为
    构造函数名(类型 1 形参1,类型2 形参2,…)
    前面已说明: 用户是不能调用构造函数的,因此无法采用常规的调用函数的方法给出实参。实参是在定义对象时给出的。定义对象的一般格式为
    类名 对象名(实参1,实参2,…);

    【例】有两个长方柱,其长、宽、高分别为: (1)12,20,25;(2)10,14,20。求它们的体积。编一个基于对象的程序,在类中用带参数的构造函数。

    #include <iostream>
    using namespace std;
    class Box
    {public:
    Box(int,int,int);        //声明带参数的构造函数
    int volume( );            //声明计算体积的函数
     private:
    int height;
    int width;
    int length;
    };
    Box∷Box(int h,int w,int len)   //在类外定义带参数的构造函数
    {height=h;
    width=w;
    length=len;
    }
    int Box∷volume( )                //定义计算体积的函数
    {return(height*width*length);
    }
    int main( )
    {Box box1(12,25,30);           //建立对象box1,并指定box1长、 
                                                     宽、高的值
    cout<<″The volume of box1 is ″<<box1.volume( )<<endl;
    Box box2(15,30,21);           //建立对象box2,并指定box2长、 
                                                    宽、高的值
    cout<<″The volume of box2 is ″<<box2.volume( )<<endl;
    return 0;
    } 
    

    程序运行结果如下:
    The volume of box1 is 9000
    The volume of box2 is 9450

    可以知道:
    (1) 带参数的构造函数中的形参,其对应的实参在定义对象时给定。
    (2) 用这种方法可以方便地实现对不同的对象进行不同的初始化。

    在这里插入图片描述

    展开全文
  • C++构造函数之委托构造函数

    千次阅读 多人点赞 2016-10-20 22:16:05
    C++构造函数之委托构造函数 C++11新标准扩展了构造函数初始值的功能,所以委托构造函数就出现了,一个委托构造函数使用它所属类的其他构造函数执行它自己的初始化过程,或者说他把自己的一些(或全部)职责委托给了...

                                                                                                                         C++构造函数之委托构造函数

    C++11新标准扩展了构造函数初始值的功能,所以委托构造函数就出现了,一个委托构造函数使用它所属类的其他构造函数执行它自己的初始化过程,或者说他把自己的一些(或全部)职责委托给了其他构造函数。

    1.定义:

       和其他构造函数一样,一个委托构造函数也有一个成员初始值列表和一个函数体。在委托构造函数内,成员初始值列表只有一个唯一的入口,就是类名本身。和其他成员初始值一样,类名后面紧跟圆括号括起来的参数列表,参数列表必须跟类中另外一个函数匹配。

    2.举例说明

       下面我们来看一个具体的例子:

       #include<iostream>

    using namespace std;

    class Date

    {

    public:

    //非委托构造函数使用对应的实参初始化成员

    Date(int year,int month,int day)

    :_year(year)

    , _month(month)

    , _day(day)

    {}

    //其余构造函数全都委托给另一个构造函数

    Date() :Date(1990,1,1)

    {}

    Date(int year) :Date(){}

    private:

    int _year;

    int _month;

    int _day;

    };

    void FunTest()

    {

    Date d;

    Date::Date(2016);

    }

    int main()

    {

    FunTest();

    system("pause");

    return 0;

    }

    分析:在Date类中,除了第一个构造函数外,其他的都委托了他们的工作,第一个构造函数接受三个实参,使用这些实参初始化数据成员,然后结束工作。其他两个构造函数把自己的初始化工作全都委托给了第一个构造函数去完成。这点可以通过对以上程序的调试来验证,在调试过程中,但需要第二个或者第三个构造函数来完成初始化工作时,再按F11调试都会跳转到第一个构造函数中去。

    展开全文
  • 文章目录函数的定义函数的的使用方法函数的返回值值传递指针传递引用传递C++引用作为函数返回值函数重载(Function Overloading)运算符重载(Operator Overloading)以成员函数的形式重载构造函数 函数的定义 函数...
  • C++构造函数默认值设置

    千次阅读 2018-11-15 10:10:35
    C++构造函数默认值设置构造函数默认值代码 构造函数默认值 C++类中构造函数设置默认值应当注意: C++类构造函数只能对排在最后的参数提供默认值; 既可以在构造函数的声明中,也可以在构造函数的实现中,提供...
  • C++构造函数调用顺序

    千次阅读 2019-06-24 09:49:26
    C++构造函数按下列顺序被调用: (1)任何虚拟基类的构造函数按照它们被继承的顺序构造; (2)任何非虚拟基类的构造函数按照它们被继承的顺序构造; (3)任何成员对象的构造函数按照它们声明的顺序调用; (4)类自己...
  • C++构造函数调用规则

    2018-08-23 16:44:24
    C++构造函数调用规则  1)当类中没有定义任何一个构造函数时,C++编译器会提供默认无参构造函数和默认拷贝构造函数  2)当类中定义了拷贝构造函数时,C++编译器不会提供无参数构造函数  3)当类中定义了任意的...
  • c++构造函数的知识在各种c++教材上已有介绍,不过初学者往往不太注意观察和总结其中各种构造函数的特点和用法,故在此我根据自己的c++编程经验总结了一下c++中各种构造函数的特点,并附上例子,希望对初学者有所帮助...
  • C++构造函数初始化列表与构造函数中的赋值的区别

    万次阅读 多人点赞 2016-12-10 15:16:51
    C++构造函数初始化列表与赋值
  • C++构造函数处理顺序

    2018-08-22 21:18:29
    C++构造函数处理顺序如下: 1、为传入的非引用实参通过拷贝构造函数建立临时变量,引用实参省略这一步。 2、调用基类构造函数。 3、处理成员变量的初始化工作,按照成员变量定义的顺序进行初始化。初始化列表里的...
  • C++构造函数explicit关键字
  • C++构造函数与析构函数

    万次阅读 2016-02-13 10:13:28
    C++构造函数与析构函数 1.构造函数 1.1什么是构造函数? 构造函数是一种特殊的成员函数,与其他成员函数不同,建立对象时自动执行,名字与类名相同,不具有任何类型,无返回值。 1.2什么时候调用构造函数? 在类对象...
  • c++构造函数之四种默认构造方式

    千次阅读 2018-04-12 17:33:15
    问题:c++构造函数的知识在各种c++教材上已有介绍,不过初学者往往不太注意观察和总结其中各种构造函数的特点和用法,故在此我根据自己的c++编程经验总结了一下c++中各种构造函数的特点,并附上例子,希望对初学者...
  • C++构造函数的调用

    千次阅读 2015-08-19 12:46:38
    很快就要找工作笔试面试啥的了,昨晚又有问我关于C++构造函数的调用问题。 C++98/03标准中有三个特殊的构造函数,默认构造函数,拷贝构造函数和赋值构造函数;C++11/14中海油基于移动语义的移动拷贝构造函数和移动...
  • C++构造函数详解及显示调用构造函数

    万次阅读 多人点赞 2018-10-08 10:55:11
    c++类的构造函数详解 一、 构造函数是干什么的 class Counter { public:  // 类Counter的构造函数  // 特点:以类名作为函数名,无返回类型  Counter()  {  ...
  • C++ 构造函数总结

    万次阅读 多人点赞 2017-05-10 16:57:22
    C++提供了构造函数来处理对象的初始化。构造函数是一种特殊的成员函数,与其他成员函数不同,构造函数不需要用户来调用它,而是建立对象时自动执行。 构造函数的名字必须与类名相同,构造函数不具有任何类型,不...
  • C++构造函数的几种写法

    千次阅读 2019-02-27 10:35:02
    C++构造函数的几种写法 ** 主要借鉴了https://blog.csdn.net/zxc024000/article/details/51153743 之前学习了构造函数的方法,但是对于类似于初始化列表的方式不太理解,于是自己在网上查阅了一些博客之后,在这里...
  • c++ 构造函数的默认参数

    千次阅读 2016-07-10 20:33:40
    C++ 构造函数的默认参数声明和定义的区别
  • C++构造函数初始化顺序 C++构造函数按下列顺序被调用:(1、2、3、4是按照优先级顺序来的!) (1)任何虚拟基类的构造函数按照它们被继承的顺序构造; (2)任何非虚拟基类的构造函数按照它们被继承的顺序构造; (3)...
  • return C++构造函数的返回值

    千次阅读 2014-11-01 16:43:39
    看到这个标题估计大家都很诧异,C++构造函数是没有返回值
  • C++ 构造函数抛出异常注意事项

    千次阅读 2015-12-02 10:40:40
    1.构造函数中抛出异常在C++构造函数中,既需要分配内存,又需要抛出异常时要特别注意防止内存泄露的情况发生。因为在构造函数中抛出异常,在概念上将被视为该对象没有被成功构造,因此当前对象的析构函数就不会被...
  • 当父类没有定义默认构造函数,定义了了自定义的构造函数时,子类定义构造函数时需要使用父类定义的构造函数,否则编译报错。 父类:没有定义默认构造函数,而是定义了其余的构造函数 子类的构造函数在定义时...
  • 【C++】C++构造函数和析构函数

    千次阅读 2017-06-26 20:51:06
    C++提供构造函数来处理对象的初始化。 构造函数是一种特殊的成员函数,不需要用户来调用,定义对象时被自动执行。 构造函数名字与类名相同,无返回类型(void也不能有哦)。可以由用户自己定义实现,根据需要设计对...
  • 构造函数 ,是一种特殊的方法 。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中 。特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的...
  • C++构造函数与传默认值的关系

    千次阅读 2015-07-27 16:28:46
    C++构造函数与传默认值的关系 类的构造函数有几种形式: 1 不为类提供任何构造函数,系统将为类提供一个空的默认构造函数,不对对象成员值做任何改变。在set函数对其赋值,由get函数进行取值。 2 自己手动为类...
  • C++构造函数初始化列表

    万次阅读 2018-02-07 19:52:47
    何为构造函数初始化列表 class Sample { public: // 构造函数内部赋值 Sample(int a) { a_ = a; } // 构造函数初始化列表 Sample(int a) : a_(a) { } private: int a_; }; 上面的代码中,Sample类的2...
  • C++构造函数构造顺序

    2019-03-29 10:15:53
    首先,任何虚拟基类构造函数按照被继承的顺序构造 然后,任何非虚拟基类构造函数按照被继承的顺序构造 最后,成员变量按照声明顺序进行构造 demo #include using namespace std; class Base { public: Base(int i) ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 47,916
精华内容 19,166
关键字:

c++构造函数

c++ 订阅