【C++】——类和对象(中)
文章目录
- 类的默认成员函数
- 构造函数
- 析构函数
- 拷贝构造函数
- 赋值运算符重载
- 运算符重载
- const成员函数
类的默认成员函数
在C++中,类(class)可以拥有多种成员函数,其中一些成员函数在类定义中没有显式声明时,编译器会隐式地为该类生成。这些由编译器自动生成的成员函数被称为默认成员函数(也称为特殊成员函数)。它们包括:
- 默认构造函数(Default Constructor)
- 析构函数(Destructor)
- 拷贝构造函数(Copy Constructor
- 拷贝赋值运算符(Copy Assignment Operator)
- 移动构造函数(Move Constructor) 和 移动赋值运算符(Move Assignment Operator),这是C+11以后引入的,比较复杂,这里就不介绍,重点将前4个。
构造函数
特征:
- 函数名和类名相同
- 无返回值
- 对象实例化时编译器自动调用对应的构造函数。
- 构造函数可以重载。
- 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦
用户显式定义编译器将不再生成。
class Data { public: //1.无参构造函数 /*Data() { int _year = 1; int _month = 1; int _day = 1; }*/ //2.带参构造函数 //Date(int year, int month, int day) //{ // _year = year; // _month = month; // _day = day; //} //3.全缺省构造函数 //Date(int year = 1, int month = 1, int day = 1) //{ // _year = year; // _month = month; // _day = day; //} private: int _year; int _month; int _day; }; int main() { Data d1; Data d2(2024,7,15); Data d3(2024); return 0; }前面我们说过:
“如果没有为类定义任何构造函数,编译器会生成一个默认构造函数。这个构造函数不接受任何参数,并且只进行成员变量的默认初始化(对于内置类型不做任何操作,对于类类型调用其默认构造函数)。如果类中定义了任何构造函数(包括带参数的构造函数),编译器就不会自动生成默认构造函数。”所以,无参构造函数和全缺省构造函数也是默认构造函数,因为这两种构造函数都可以不用传参。这三种默认构造只能存在一个,不能同时存在。
总结:不传实参就可以调用的构造就叫默认构造。
析构函数
析构函数和构造函数功能相反,析构函数不是对对象本身的销毁,而是对对象中资源的清理工作。
如果没有资源需要释放,就不需要析构函数了。
特征:
- 析构函数名是在类名前加上字符 ~。
- . 无参数无返回值类型。
- 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载
- 对象生命周期结束时,C++编译系统系统自动调用析构函数。
- 跟构造函数类似,我们不写编译器自动生成的析构函数对内置类型成员不做处理,自定义类型成员会调用他的析构函数。
- 如果类没有申请资源,析构可以不用写。如果没有写析构,也会自动调用析构函数。
- 如果有资源申请,一定要写析构函数,否则会造成内存泄漏。
#include using namespace std; typedef int STDataType; class Stack { public: Stack(int n = 4) { _a = (STDataType*)malloc(sizeof(STDataType) * n); if (nullptr == _a) { perror("malloc申请空间失败"); return; } _capacity = n; _top = 0; } // ... ~Stack() { free(_a); _a = nullptr; _top = _capacity = 0; } private: STDataType* _a; size_t _capacity; size_t _top; }; // 两个Stack实现队列 class MyQueue { public: // 编译器默认生成MyQueue的析构函数调用了Stack的析构,释放的Stack内部的资源 // 显示写析构,也会自动调用Stack的析构 ~MyQueue() { cout MyQueue mq; //stack st1; //stack st2; return 0; } public: Date(int year = 1, int month = 1, int day = 1) { _year = year; _month = month; _day = day; } // error C2652: “Date”: 非法的复制构造函数: 第一个参数不应是“Date” // Date d2(d1) Date(const Date& d) { _year = d._year; _month = d._month; _day = d._day; } void Print() { cout // return d1._year == d2._year // && d1._month == d2._month // && d1._day == d2._day; //} bool operator==(Date d2) { return _year == d2._year && _month == d2._month && _day == d2._day; } int main() { Date x1(2024, 7, 10); Date x2(2024, 7, 11); //operator==(x1, x2); //x1 == x2; x1.operator==(x2); x1 == x2; return 0; } return d1._year == d2._year && d1._month == d2._month && d1._day == d2._day; } int main() { // 运算符重载函数可以显示调用 operator==(d1, d2); // 编译器会转换成 operator==(d1, d2); d1 == d2; return 0; } //默认是private int x; int y; public: func(int xp = 0, int yp = 0) { x = xp; y = yp; } //const成员函数内无法修改类的数据成员,否者编译器会报错 void print() const { x = 5;//试图修改x 将引发编译器报错 cout //默认是private int x; int y; public: func(int xp = 0, int yp = 0) { x = xp; y = yp; } void Print2() { cout //x=5;//试图修改成员变量 将引发编译器报错 Print2(); //试图调用非const成员 引发编译器报错 cout
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!
