类和对象_2(构造函数,析构函数,拷贝构造)

目录

 

类的默认成员函数

构造函数

析构函数

拷贝构造函数


类的默认成员函数

           一个类中若没有成员则称为空类。

           任何一个类都会生成6个默认成员函数:

                                                                         1. 构造函数         // 初始化

                                                                         2. 拷贝构造函数  // 使用同类对象初始化创建对象

                                                                         3. 析构函数         // 清理

                                                                         4. 赋值操作符重载   // 将一个对象赋值给另一个对象

                                                                         5. 取地址操作符重载   // 普通对象取地址

                                                                         6. const修饰的取地址操作符重载    // const对象取地址

构造函数

             概念:

                构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员都有一个合适的 

        初始值,并且在对象生命周期内只调用一次

             特性:

                 1.  函数名与类名相同

                 2.  无返回值

                 3.  对象构造(实例化时) 编译器自动调用对应的构造函数

                 4.  构造函数可以重载

                 5.  如果类中没有显示定义构造函数,则编译器会自动生成一个默认的构造函数,一旦用户显示定义,编译器将不再生

                成;(若有无参的对象可以自己显示定义 或在有 参的构造函数添加缺省值<缺省构造函数>)

               注:无参与缺省只能存在一个

                6.  一个 无参的构造函数和缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个;

                7.  默认的构造函数会对自定义类型成员调用它的默认成员函数;

                8.  成员变量命名风格:成员变量前加 “_” 或 其它前缀。

析构函数

           概念:

            与构造函数功能相反,析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成类的一些资源清理工作。


typedef int DataType;

class SeqList
{
	DataType *_array;
	size_t _size;
	size_t _capacity;
public:
	SeqList(size_t capacity = 10)
	{
		_array = (DataType*)malloc(sizeof(DataType) * capacity);
		if (nullptr == _array)
		{
			assert(0);
		}
		_capacity = capacity;
		_size = 0;
	}

	~SeqList()
	{
		if (_array)
		{
			free(_array);
			_array = nullptr;
			_capacity = 0;
			_size = 0;
		}
	}

	void PushBack(const DataType data)
	{
		_array[_size++] = data;
	}

	void PopBack()
	{
		--_size;
	}
};

void TestFunc()
{
	SeqList s;
	s.PushBack(1);
	s.PushBack(2);
	s.PushBack(3);

	s.PopBack();
}

int main()
{
	TestFunc();
	return 0;
}

          特性:

              1.  析构函数名是在类名前加“~”;

              2.  无参数无返回值(不能重载)

             3 . 一个类有且只有一个析构函数。若未显示定义则系统会自动生成默认的析构函数

             4.  对象生命周期结束时,C++编译系统自动调用析构函数。

             5.  编译器生成的默认析构函数,对会自定类型成员调用它的析构函数。

       为什么构造函数有参数而析构函数没有参数?

      析构函数是对象销毁时由编译器来调,对象将要消亡。

拷贝构造函数

在创建对象时,为了创建一个与一个对象一模一样的新对象 ----> 拷贝构造函数

                       概念:

                             只有单个形参,该形参对本类类型对象的引用(一般常用const修饰,防止调用时修改原来成员变量),在已存在的类类型对象创建新对象时由编译器自动调用

 

           为什么一定要传递引用?

           若传值,需要创建一个临时对象Date(const Date d)来接收,然后又传值引发对象的拷贝,这样下去将会无限调用。

             特征:

                 1.  拷贝构造函数是构造函数的一个重载形式

                 2.  拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用

                 3.  若未显示定义,系统生成默认的拷贝构造函数。默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷                   贝,或值拷贝。

           既然系统会自动生成拷贝构造,为什么还要有自定义拷贝构造呢?

typedef int Datatype;

class SeqList
{
	Datatype *_array;
	size_t _size;
	size_t _capacity;
public:
	SeqList(size_t capacity = 10)
	{
		_array = (Datatype*)malloc(sizeof(Datatype)*capacity);
		if (nullptr == _array){
			assert(0);
		}

		_capacity = capacity;
		_size = 0;
	}

	~SeqList()
	{
		if (_array){
			free(_array);
			_array = nullptr;
			_capacity = 0;
			_size = 0;
		}
	}

	void PushBack(const Datatype data)
	{
		_array[_size++] = data;
	}

	void PopBack()
	{
		--_size;
	}
};

int main()
{
	SeqList d1;
	SeqList d2(d1);
	return 0;
}

            调用上面程序,若采用默认拷贝构造的方式就会报错。所以在涉及资源管理时应自定义拷贝构造函数。

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值