yo!这里是类的默认成员函数

目录

前言

默认成员函数

构造函数

1.介绍

2.注意点

析构函数

1.介绍

2.注意点

拷贝构造函数

1.介绍

2.注意点

赋值运算符重载

1.介绍

2.注意点

取地址及const取地址操作符重载

1.介绍

2.注意点

后记


前言

        在学习c++的过程中,我们知道,c++是面向对象的语言,有这样三个特性——封装、继承、多态,在类和对象阶段研究封装的特性,而类的默认成员函数正是实现封装特性的大框架,在认识默认成员函数之后,对于类的封装特性会有进一步的理解,这也属于c++后续知识的根基中的根基,务必对此要反复学习,下面就来详细介绍一下类的默认成员函数。

默认成员函数

        默认成员函数是用户没有显示实现,编译器自动生成的成员函数,在一个空类中,编译器会自动生成6个默认构造函数,分别为默认构造函数、默认析构函数、默认拷贝构造函数、赋值运算符重载、取地址及const取地址操作符重载,在这六个之中,前四个较为重要,最后两个较为不重要,因为很少需要用户实现,使用默认生成的即可。

        有同学会说,既然编译器可以自动生成,那我们为什么还要学习它们,直接使用编译器生成的不就行了?不可以,因为自动生成的默认成员函数无法满足所有类的实现,无法完美得当的实现一个类的初始化、销毁等操作,大部分的类还是会需要用户自己来实现,下面会针对每一个默认成员函数进行具体的讲解。

  • 构造函数

1.介绍

        构造函数是一个特殊的成员函数,作用并不是开辟空间,而是初始化对象,在对象整个生命周期内只调用一次。

特征:

        ①.构造函数名与类名相同;

        ②.函数无返回值;

        ③.无需用户调用,而是编译器自动调用;

        ④.可重载。

2.注意点

        ①.如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,当用户显式定义,编译器将不再生成;

        ②.默认构造函数包括 用户显示定义的无参的构造函数和全缺省的构造函数 以及 编译器自动生成的构造函数,并且默认构造函数只能有一个;

        ③.当用户显示定义了一个构造函数,既不是无参也不是全缺省,同时编译器也不会自动生成,那么就会报错,提示无默认构造函数可用;

        ④.(重要)大部分类都需要用户自己写构造函数,只有内置类型不需要初始化或者无内置类型,只有自定义类型的类不需要显示写,因为自定义类型会去调用自己的构造函数。(内置类型包括int、char......,自定义类型包括struct、class等自定义出来的类型)

eg:

class Date
{
public:
     Date(int year = 1900, int month = 1, int day = 1)  //全缺省的构造函数
     {
         _year = year;
         _month = month;
         _day = day;
     }
private:
     int _year;
     int _month;
     int _day;
};
  • 析构函数

1.介绍

        析构函数是一个特殊的成员函数,作用并不是销毁对象,而是销毁对象中的资源,在对象整个生命周期内只调用一次。

特征:

        ①.析构函数名是在类名前加上字符 ~;

        ②.函数无返回值;

        ③.无需用户调用,而是编译器自动调用,一个类只能有一个析构函数;

        ④.不可重载。

2.注意点

        ①.与构造函数类似,不处理内置类型,自定义类型会去调用自己的析构函数,因为内置类型会在函数结束后被系统将内存回收掉;

        ②.(重要)若类中没有申请资源,析构函数可以不写,直接使用编译器生成的默认析构函数,当有资源申请时,一定要写,否则会造成资源泄漏。

eg:

class Stack
{
public:
	Stack(int capacity = 0)
	{
        //...
	}

	~Stack()
	{
		delete[] _arr;
		_arr = nullptr;
		_top = _capacity = 0;
	}

private:
	T* _arr;
	size_t _top;
	size_t _capacity;
};
  • 拷贝构造函数

1.介绍

        拷贝构造函数是一个特殊的成员函数,作用是使用已有对象创建新对象。

特征:

        ①.是构造函数的一个重载形式;

        ②.只有一个形参,就是已存在对象的引用,常用const修饰,即拷贝此对象。

2.注意点

        ①.参数必须是引用,若是传值调用,会报错,因为传值调用本身就会调用拷贝构造函数,导致无穷调用;

        ②.若未显式定义,编译器会生成默认的拷贝构造函数,但是浅拷贝,需要深拷贝的地方一定要自己显示定义拷贝构造函数;

        ③.在编译器生成的默认拷贝构造函数中,内置类型是浅拷贝,而自定义类型则是调用自己的拷贝构造函数;

        ④.(重要)类中如果没有申请资源,拷贝构造函数是否写都可以;当涉及到资源申请时,则拷贝构造函数是一定要写的,否则就是浅拷贝。

eg:

class Date
{
public:
     Date(int year, int minute, int day)
     {
         //...
     }
     Date(const Date& d)   //拷贝构造函数
     {
         //...
     }
private:
     int _year;
     int _month;
     int _day;
};
  • 赋值运算符重载

1.介绍

        赋值运算符重载,实现赋值运算符(=)可适用于自定义类型,语法格式:T& operator=(const T& t){} 。

特征:

        ①.const T&,传递引用可以提高传参效率;

        ②.T&,返回引用是为了支持连续赋值;

        ③.返回*this ,要符合连续赋值的含义。

2.注意点

        ①.赋值运算符只能重载成类的成员函数,不能重载成全局函数,因为赋值运算符如果不显式实现,编译器会生成默认,此时用户在类外自己实现一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载发生冲突;

        ②.用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以浅拷贝形式进行拷贝;

        ③.无需用户调用,而是编译器自动调用,一个类只能有一个析构函数;

        ④.如果类中未涉及到资源管理,赋值运算符是否实现都可以,当涉及到资源管理则必 须要显示实现。

eg:

class Time
{
public:
     Time()
     {
         //...
     }
     Time& operator=(const Time& t)   //赋值运算符重载
     {
         if (this != &t)
         {
             _hour = t._hour;
             _minute = t._minute;
             _second = t._second;
         }
         return *this;
     }
private:
     int _hour;
     int _minute;
     int _second;
};
  • 取地址及const取地址操作符重载

1.介绍

        取地址操作符重载,与赋值运算符重载类似,实现取地址操作符(&)可适用于自定义类型。

2.注意点

        一般不需要用户自己定义,直接使用编译器生成的默认取地址重载即可,特殊情况才需要自己写。

 eg:

class Date
{ 
public :
     Date* operator&()   //取地址操作符重载
     {
         return this ;
     }
     const Date* operator&() const   //const取地址操作符重载
     {
         return this ;
     }
private :
     int _year ; // 年
     int _month ; // 月
     int _day ; // 日
};

后记

        在学习类的默认成员函数时,会存在很多细节没能够琢磨明白,或者说很难理解明白,一定要反复吸收,反复理解,才能够摸清一点门道,作为c++的根基中的根基,希望大家能够重视对类和对象的学习,如果有什么问题,欢迎在评论区讨论或者私我哦,拜拜。


猜你喜欢

转载自blog.csdn.net/phangx/article/details/131740930