目录🌷默认成员函数🌷构造函数🌺引例🌺构造函数的概念及特性🌷析构函数🌺析构函数的特性🌷默认成员函数 上一章中我们谈到,如果一个类中什么成员也没有,那么这个类就叫作空类。其实这么说是不太
上一章中我们谈到,如果一个类中什么成员也没有,那么这个类就叫作空类
。其实这么说是不太严谨的,因为一个类不可能什么都没有
。
当我们定义好一个类,不做任何处理时,编译器会自动生成以下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();
class Date
{
public:
//若用户没有显示定义,则编译器自动生成。
private:
int _year;
int _month;
int _day;
};
内置类型
(基本类型)和自定义类型
。内置类型就是语言提供的数据类型,如:int、char、double…,自定义类型就是我们使用class、struct、uNIOn等自己定义的类型。🌼举例🌼
🌼默认构造函数对内置类型🌼
class Date
{
public:
//此处不对构造函数做显示定义,测试默认构造函数
void print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
void TestDate1()
{
Date d1;
d1.print();
}
🌼默认构造函数对自定义类型🌼
class stack
{
public:
//此处对stack构造函数做显示定义
stack()
{
cout <<"stack()" << endl;
_a = nullptr;
_top = _capacity = 0;
}
private:
int* _a;
int _top;
int _capacity;
};
class queue
{
public:
//此处不对queue构造函数做显示定义,测试默认构造函数
private:
//自定义类型成员
stack _s;
};
void TestQueue()
{
queue q;
}
queue
对象时,默认构造函数对自定义成员_s
做了处理,调用了它的默认构造函数stack()
。这一波蜜汁操作让很多C++使用者感到困惑与不满,为什么要针对内置类型和自定义类型做不同的处理呢?终于,在C++11中针对内置类型成员不初始化的缺陷,又打了补丁,即:
🌼举例🌼
class Date
{
public:
//...
void print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
//使用默认值
int _year = 0;
int _month = 0;
int _day = 0;
};
void TestDate2()
{
Date d2;
d2.print();
}
默认值
:若不对成员变量做处理,则使用默认值。🌼举例🌼
class Date
{
public:
//无参的默认构造函数
//Date()
//{
//}
//全缺省的默认构造函数
Date(int year = 0, int month = 0, int day = 0)
{
_year = year;
_month = month;
_day = day;
}
void print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year = 0;
int _month = 0;
int _day = 0;
};
析构函数
与构造函数
的特性相似,但功能有恰好相反。构造函数是用来初始化对象的,析构函数是用来销毁对象
的。
析构函数并不是对对象本身进行销毁
(因为局部对象出了作用域会自行销毁,由编译器来完成),而是在对象销毁时会自动调用析构函数,对对象内部的资源做清理
(例如stack _s中的int* a)。同样,有了析构函数,我们再也不用担心创建对象(或定义变量)后由于忘记释放内存而造成内存泄漏
了。
🌼举例🌼
class Stack
{
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();
}
~
;🌼举例🌼
class Date
{
public:
Date()
{
cout << "Date()" << endl;
}
~Date()
{
cout << "~Date()" << endl;
}
private:
int _year = 0;
int _month = 0;
int _day = 0;
};
void TestDate3()
{
Date d3;
//d3生命周期结束时自动调用构造函数
}
为便于观察,我们可以在析构函数内部写点儿东西。
🌼举例🌼
class stack
{
public:
//此处对stack构造函数做显示定义
stack()
{
cout <<"stack()" << endl;
_a = nullptr;
_top = _capacity = 0;
}
~stack()
{
cout << "~Stack()" << endl;
free(_a);
_a = nullptr;
_top = _capacity = 0;
}
private:
int* _a;
int _top;
int _capacity;
};
class queue
{
public:
//此处不对queue构造函数做显示定义,测试默认构造函数
private:
//自定义类型成员
stack _s;
};
void TestQueue1()
{
queue q;
}
为什么析构函数不像构造函数那样区分内置类型与自定义类型呢
?Date
类;有资源申请时,一定要写,否则会造成资源泄漏,比如stack
类。到此这篇关于C++修炼之构造函数与析构函数的文章就介绍到这了,更多相关C语言 构造函数与析构函数内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: C++修炼之构造函数与析构函数
本文链接: https://www.lsjlt.com/news/202770.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0