行业知识
【C++】类的默认成员函数(上)
2026-11-08 05:04:43
来源:互联网转载
博客主页: 小���失眠啦.
系列专栏:《C语言》 《数据结构》 《C++》 《Linux》 《Cpolar》
❤️感谢大家点赞收藏⭐评论✍️
文章目录
- 一、默认成员函数
- 二、构造函数
- 构造函数的概念及特性
- 三、析构函数
- 析构函数的特性
- 四、拷贝构造函数
- 拷贝构造函数的特性
一、默认成员函数
上一章中我们谈到,如果一个类中什么成员也没有,那么这个类就叫作空类。其实这么说是不太严谨的,因为一个类不可能什么都没有。
当我们定义好一个类,不做任何处理时,编译器会自动生成以下6个默认成员函数:
- 默认成员函数:如果用户没有手动实现,则编译器会自动生成的成员函数。
- 构造函数:主要完成初始化工作;
- 析构函数:主要完成清理工作;
- 拷贝构造:使用一个同类的对象初始化创建一个对象;
- 赋值重载:把一个对象赋值给另一个对象;
- 取地址重载:普通对象取地址操作;
- 取地址重载(const):const对象取地址操作;
本章我们将学习四个默认成员函数——构造函数与析构函数——拷贝构造 与赋值重载
二、构造函数
在C语言阶段,我们实现栈的数据结构时,有一件事很苦恼,就是每当创建一个stack对象(之前叫作定义一个stack类型的变量)后,首先得调用它的专属初始化函数StackInit来初始化对象。
typedef int dataOfStackType;typedef struct stack{dataOfStackType* a;int top;int capacity;}stack;void StackInit(stack* ps);//... int main() { stack s; StackInit(&s); //... return 0; }这不免让人觉得有点麻烦。在C++中,构造函数为我们很好的解决了这一问题。
构造函数的概念及特性
构造函数是一个特殊的成员函数。构造函数虽然叫作构造,但是其主要作用并不是开辟空间创建对象,而是初始化对象。
构造函数之所以特殊,是因为相比于其它成员函数,它具有如下特性:
- 函数名与类名相同;
- 无返回值;
- 对象实例化时,编译器自动调用对应的构造函数;
- 构造函数可以重载;
举例
class Date{public://无参的构造函数Date(){};//带参的构造函数Date(int year,int month,int day){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;};void TestDate(){Date d1;//调用无参构造函数(自动调用)Date d2(2023, 3, 29);//调用带参构造函数(自动调用)}特别注意
- 创建对象时编译器会自动调用构造函数,若是调用无参构造函数,则无需在对象后面使用()。否则会产生歧义:编译器无法确定你是在声明函数还是在创建对象。
错误示例
//错位示例Date d3();
- 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。
class Date{public://若用户没有显示定义,则编译器自动生成。/*Date(int year,int month,int day){_year = year;_month = month;_day = day;}*/private:int _year;int _month;int _day;};- 默认生成构造函数,对内置类型成员不作处理;对自定义类型成员,会调用它的默认构造函数;
- C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如:int、char、double…,自定义类型就是我们使用class、struct、union等自己定义的类型。
举例
默认构造函数对内置类型
class Date{public://此处不对构造函数做显示定义,测试默认构造函数/*Date(){}*/void print(){cout Date d1;d1.print();}public://此处对stack构造函数做显示定义stack(){cout public://此处不对queue构造函数做显示定义,测试默认构造函数/*queue(){}*/private://自定义类型成员stack _s;};void TestQueue(){queue q;}public://...void print(){cout Date d2;d2.print();}public://无参的默认构造函数//Date()//{//}//全缺省的默认构造函数Date(int year = 0, int month = 0, int day = 0){_year = year;_month = month;_day = day;}void print(){cout public:Stack(){//...}void Push(int x){//...}bool Empty(){// ...}int Top(){//...}void Destory(){//...}private:// 成员变量int* _a;int _top;int _capacity;};void TestStack(){Stack s;st.Push(1);st.Push(2);//过去需要手动释放st.Destroy();}public:Date(){cout cout Date d3;//d3生命周期结束时自动调用构造函数}public://此处对stack构造函数做显示定义stack(){cout cout public://此处不对queue构造函数做显示定义,测试默认构造函数/*queue(){}*/private://自定义类型成员stack _s;};void TestQueue1(){queue q;}public://构造函数Date(){cout cout cout Date d1;//调用拷贝构造创建对象Date d2(d1);}public://错误示例//如果这样写,编译器就会直接报错,但我们现在假设如果编译器不会检查,//这样的程序执行起来会发生什么Date(const Date d){_year = d._year;_month = d._month;_day = d._day;}private:int _year = 0;int _month = 0;int _day = 0;};void TestDate(){Date d1;//调用拷贝构造创建对象Date d2(d1);}public://构造函数Date(int year = 0, int month = 0, int day = 0){//cout cout Date d1(2023, 3, 31);//调用拷贝构造创建对象Date d2(d1);d2.print();}public:stack(int defaultCapacity=10){_a = (int*)malloc(sizeof(int)*defaultCapacity);if (_a == nullptr){perror("malloc fail");exit(-1);}_top = 0;_capacity = defaultCapacity;}~stack(){cout _a[_top++] = n;}void print(){for (int i = 0; i
- 默认成员函数:如果用户没有手动实现,则编译器会自动生成的成员函数。
- 拷贝构造函数的特性