zoukankan      html  css  js  c++  java
  • C++类中隐藏的六个默认函数

    Test类中隐藏的六个默认的函数

    class Test
    {
    public:
    	//默认的构造函数
    	Test()//析构函数 
    	~Test()//拷贝构造函数 
    	Test(const Test &t)//赋值函数 
    	Test& operator=(const Test &x)//一般对象取地址函数 
    	Test* operator&()//常对象取地址函数 
    	const Test* operator&()constprivate:
    		int data;
    		//int *data;
    };
    

    1.构造函数

    作用:对象所在的内存空间做初始化 、给对象赋资源
    特点

    1. 可以重载 :可以根据实际需要进行缺省的、多参重载
    2. 不依赖对象:对象无法调用构造函数,只能在对象定义点被调用
    //成员函数类外实现,需在函数名前指定作用域,否则编译器会认为在定义一个普通的函数
    Test::Test()	//类中默认的构造函数
    {
    }
    //此外,构造函数可以支持重载,我们可以根据需要自己写一些构造函数
    //需要注意的是,如果我们自己写了构造函数,那么编译器就不会提供默认的构造函数了
    Test::Test(int d = 0 )	//缺省的构造函数
    {
    	data = d;
    }
    Test::Test(int d = 0 ):data(d)	//缺省的构造函数,用初始化器的方式初始化
    {
    }
    

    两者初始化的区别在于,初始化器是真正意义上的初始化,它告诉编译器在实例化对象的时候以何种方式对成员赋值,而在前者的赋值规则写在了构造函数内部,是在已经生成了成员变量之后再进行的赋值操作。
    初始化器实例:比如以下操作,成员变量定义为const类型,在C语言中const类型是一个常变量在定义的时候可以不初始化,而在C++中规定const类型为一个常量,定义时必须初始化。所以以下操作只能使用初始化器的方式初始化。

    class Test
    {
    public:
    	Test(int a)
    		:ma(a)
    	{
    		//ma = a;
    	}
    private:
    	const int ma;
    };
    

    此外,如果有多个成员变量需要使用初始化器的方式初始化,需要注意一点细节,初始化的顺序与成员变量的定义顺序相关。如以下程序,可以写成Test(int a):ma(mb), mb(a){}Test(int a):mb(a),ma(mb){}因为成员变量的定义顺序为int mb; int ma;,也就是说赋值顺序与初始化器无关,只与成员变量被定义的顺序有关。

    class Test
    {
    public:
    	Test(int a):ma(mb), mb(a)	//mb先被定义出来,先给mb赋值,再给ma赋值
    	{
    	}
    	Test(int a):mb(ma), ma(a)	//error mb先定义出来,此时ma还未被定义,所以mb(ma)赋值无效,最终结果为,mb无效值,ma=a
    	{
    	}
    	void Show()
    	{
    		std::cout << "ma: " << ma << std::endl;
    		std::cout << "mb: " << mb << std::endl;
    	}
    private:
    	int mb;
    	int ma;
    };
    

    2.析构函数

    作用:释放对象所占的其他资源。
    特点

    1. 不可重载 : 对象销毁时会调用析构函数,并释放空间。
    2. 依赖对象:可用手动调用,但是不建议,因为对象销毁时会自动调用,如果手动调用可能会引起内存空间的重复析构导致程序崩溃
    //默认的析构函数 
    Test::~Test()
    {		//没有额外的资源,什么都不写
    }
    
    //如果程序中有额外的空间需要释放
    class Test
    {
    public:
    	//构造函数 
    	Test()
    	{
    		data = new int;		//data指向一块堆区内存
    	}
    	//析构函数
    	~Test();
    private:
    		int* data;
    };
    
    //析构函数 
    Test::~Test()
    {
    	delete data;	//把额外空间的释放写进析构函数
    }
    

    3.拷贝构造函数

    作用:拿一个已存在的对象来生成相同类型的新对象
    注意:类中提供的拷贝构造函数为一个浅拷贝类型,即如果成员变量中含有指针类型,它在进行拷贝构造的时候不会进行额外空间的开辟,最终会造成函数析构时的错误。

    class Test
    {
    public:
    	//构造函数 
    	Test()
    	{
    		data = new int;		//data指向一块堆区内存
    	}
    	//拷贝构造函数 
    	Test(const Test &t);	//一定要传引用,否则在开辟形参的过程中会递归的调用拷贝构造函数来构造形参,而函数始终无法执行
    private:
    		int* data;
    };
    
    //默认的拷贝构造函数 
    Test::Test(const Test &t)
    {
    	data = t.data;		//浅拷贝,只把现有的成员变量进行拷贝,没有对堆区内存进行拷贝,使多个对象的data指向了同一片堆区空间,在对象销毁时会造成空间的重复释放引发程序崩溃。
    }
    //拷贝构造函数
    Test::Test(const Test &t)
    {
    	data = new int;		//如果是字符类型data = new char[strlen(t.data) + 1];
    	strcpy_s(data,sizeof(int), t.data);
    }
    

    4.赋值运算符的重载函数

    作用:拿一个已存在的对象给相同类型的已存在对象赋值
    实现步骤

    1. 自赋值判断
    2. 释放旧资源
    3. 生成新资源
    4. 赋值
    class Test
    {
    public:
    	//构造函数 
    	Test()
    	{
    		data = new int;		//data指向一块堆区内存
    	}
    	//赋值函数
    	Test& operator=(const Test &x);	//以自身类类型的引用的方式返回
    private:
    		int* data;
    };
    
    //默认的赋值函数(浅拷贝)
    Test& operator=(const Test &x)
    {
    	if(this!=&x)		//自赋值判断
    	{
    		data=x.data;	//浅拷贝
    	}
    	return *this;		//返回自身类类型的引用
    }
    //赋值函数(深拷贝)
    Test& operator=(const Test &x)
    {
    	if(this!=&x)		//自赋值判断
    	{
    		delete[] data;	//释放原资源,比如 a = 4, b = 5, a = b此时a放弃原先的资源 4
    		data = new int;
    		strcpy_s(data,sizeof(int), t.data);
    	}
    	return *this;		//返回自身类类型的引用
    }
    

    5.一般对象取地址函数

    //一般对象取地址函数 
    Test::Test* operator&()
    {
    	return this;
    }
    

    6.常对象取地址函数

    //常对象取地址函数 
    const Test::Test* operator&()const
    {
    	return this;
    }
    
  • 相关阅读:
    os.remove some jpgs
    shutil.rmtree, os.path, delete sub-folders, format
    How to create folder
    valgrind
    gstream
    TP TN FP FN
    tensor flow
    接口中静态方法和默认方法
    JAVA基础09
    JAVA基础08
  • 原文地址:https://www.cnblogs.com/TaoR320/p/12680160.html
Copyright © 2011-2022 走看看