【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
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。