C++ 复习总结记录三

打印 上一主题 下一主题

主题 1012|帖子 1012|积分 3036

C++ 复习总结记录三

主要内容
1、类的六个默认成员函数
2、构造函数
3、析构函数
4、拷贝构造函数
5、赋值运算符重载
6、const 成员函数
7、取所在及 const 取所在操纵符重载
一 类的六个默认成员函数

如果一个类中什么成员都没有,简称为空类。空类中并不是什么都没有,编译器会自动生成六个默认成员函数(用户没有显式实现,编译器自动生成的成员函数称为默认成员函数)
  1. class Date {};
复制代码
六个默认成员函数
  1. //初始化和清理
  2. 构造函数,完成初始化
  3. 析构函数,完成清理
  4. //拷贝复制
  5. 拷贝构造函数,使用同类对象初始化创建对象
  6. 赋值重载,把一个对象赋值给另一个对象
  7. //取地址重载
  8. 普通取地址函数
  9. const 取地址函数
复制代码
二 构造函数

2.1 概念

构造函数是一个特殊的成员函数,名字与类名雷同,创建类范例对象时由编译器自动调用,以保证每个数据成员都有 一个符合的初始值,而且在对象整个生命周期内只调用一次
注意,构造函数固然名称叫构造,但是构造函数任务不是开空间创建对象,而是初始化对象,特征如下
1、函数名与类名雷同
2、无返回值
3、对象实例化时编译器自动调用其构造函数
4、构造函数可以重载
  1. class Date
  2. {
  3. public:
  4.     // 1.无参构造函数
  5.     Date() {}
  6.     // 2.带参构造函数
  7.     Date(int year, int month, int day)
  8.     {
  9.         _year = year;
  10.         _month = month;
  11.         _day = day;
  12.     }
  13. private:
  14.     int _year;
  15.     int _month;
  16.     int _day;
  17. };
  18. void TestDate()
  19. {
  20.     Date d1; // 调用无参构造函数
  21.     Date d2(2015, 1, 1); // 调用带参的构造函数
  22. }
复制代码
2.2 注意要点

注意 : 如果通过无参构造函数创建对象时,对象后面不消跟括号,否则就成了函数声明
  1. void TestDate()
  2. {
  3.         //warning C4930: “Date d3(void)”: 未调用原型函数
  4.         //以下代码的函数 : 声明了d3函数, 该函数无参, 返回一个日期类型对象
  5.     Date d3();
  6. }
复制代码
类中没有显式定义构造函数,编译器会自动生成一个无参的默认构造函数,一旦显式定义编译器将不再生成
  1. class Date
  2. {
  3. public:
  4.     // 如果用户显式定义了构造函数,编译器将不再生成
  5.     /*
  6.      Date(int year, int month, int day)
  7.      {
  8.          _year = year;
  9.          _month = month;
  10.          _day = day;
  11.      }
  12.         */
  13.     void Print()
  14.     {
  15.         cout << _year << "-" << _month << "-" << _day << endl;
  16.     }
  17. private:
  18.     int _year;
  19.     int _month;
  20.     int _day;
  21. };
  22. int main()
  23. {
  24.     // 将 Date 类中构造函数屏蔽后,代码可以通过编译,因为编译器生成了一个无参的默认构造函数
  25.     // 将 Date 类中构造函数放开,代码编译失败,因为一旦显式定义任何构造函数,编译器将不再生成
  26.     // 无参构造函数,放开后报错:error C2512: “Date”: 没有合适的默认构造函数可用
  27.     Date d1;
  28.     return 0;
  29. }
复制代码
2.3 默认构造函数作用

C++ 把范例分成内置范例(根本范例,语言提供的数据范例,如 int / char … 等)和自定义范例( class / struct / union 等自定义的范例),默认构造函数会对自定范例成员调用它的默认构造函数
  1. class Time
  2. {
  3. public:
  4.     Time()
  5.     {
  6.         cout << "Time()" << endl;
  7.         _hour = 0;
  8.         _minute = 0;
  9.         _second = 0;
  10.     }
  11.    
  12. private:
  13.     int _hour;
  14.     int _minute;
  15.     int _second;
  16. };
  17. class Date
  18. {
  19. private:
  20.     // 基本类型(内置类型)
  21.     int _year;
  22.     int _month;
  23.     int _day;
  24.     // 自定义类型
  25.     Time _t;
  26. };
  27. int main()
  28. {
  29.     Date d;
  30.     return 0;
  31. }
复制代码
注意:C++11 中针对内置范例成员不初始化的缺陷打了补丁,内置范例成员变量在类中声明时可给默认值
  1. class Time
  2. {
  3. public:
  4.     Time()
  5.     {
  6.         cout << "Time()" << endl;
  7.         _hour = 0;
  8.         _minute = 0;
  9.         _second = 0;
  10.     }
  11.    
  12. private:
  13.     int _hour;
  14.     int _minute;
  15.     int _second;
  16. };
  17. class Date
  18. {
  19. private:
  20.     // 基本类型(内置类型)
  21.     int _year = 1970;
  22.     int _month = 1;
  23.     int _day = 1;
  24.     // 自定义类型
  25.     Time _t;
  26. };
  27. int main()
  28. {
  29.     Date d;
  30.     return 0;
  31. }
复制代码
2.4 默认构造函数

无参构造函数、全缺省构造函数、编译器默认生成的构造函数,都是默认构造函数,且默认构造函数只能有一个
  1. class Date
  2. {
  3. public:
  4.     Date()
  5.     {
  6.         _year = 1900;
  7.         _month = 1;
  8.         _day = 1;
  9.     }
  10.    
  11.     Date(int year = 1900, int month = 1, int day = 1)
  12.     {
  13.         _year = year;
  14.         _month = month;
  15.         _day = day;
  16.     }
  17.    
  18. private:
  19.     int _year;
  20.     int _month;
  21.     int _day;
  22. };
  23. void Test()
  24. {
  25.     Date d1; //Date包含多个构造函数, 无法通过编译
  26. }
复制代码
三 析构函数

3.1 概念

析构函数:与构造函数功能相反,完成对象中资源的清理工作
它不是完成对对象本身的销毁,局部对象销毁工作由编译器完成,对象在销毁时会自动调用析构函数
析构函数特征如下
1、析构函数名是在类名前加上字符 ~
2、无参数无返回值范例
3、一个类只能有一个析构函数,若未显式定义,系统会自动生成默认析构函数(注意:析构函数不能重载)
4、对象生命周期竣事时,编译器自动调用析构函数
  1. typedef int DataType;
  2. class Stack
  3. {
  4. public:
  5.     Stack(size_t capacity = 3)
  6.     {
  7.         _array = (DataType*)malloc(sizeof(DataType) * capacity);
  8.         if (NULL == _array)
  9.         {
  10.             perror("malloc申请空间失败!!!");
  11.             return;
  12.         }
  13.         _capacity = capacity;
  14.         _size = 0;
  15.     }
  16.    
  17.     void Push(DataType data)
  18.     {
  19.         // CheckCapacity();
  20.         _array[_size] = data;
  21.         _size++;
  22.     }
  23.    
  24.     // 其他方法...
  25.     ~Stack()
  26.     {
  27.         if (_array)
  28.         {
  29.             free(_array);
  30.             _array = NULL;
  31.             _capacity = 0;
  32.             _size = 0;
  33.         }
  34.     }
  35.    
  36. private:
  37.     DataType* _array;
  38.     int _capacity;
  39.     int _size;
  40. };
  41. void TestStack()
  42. {
  43.     Stack s;
  44.     s.Push(1);
  45.     s.Push(2);
  46. }
复制代码
3.2 默认析构函数作用

默认析构函数,对自定范例成员调用它的析构函数
  1. class Time
  2. {
  3. public:
  4.     ~Time()
  5.     {
  6.         cout << "~Time()" << endl;
  7.     }
  8. private:
  9.     int _hour;
  10.     int _minute;
  11.     int _second;
  12. };
  13. class Date
  14. {
  15. private:
  16.     // 基本类型(内置类型)
  17.     int _year = 1970;
  18.     int _month = 1;
  19.     int _day = 1;
  20.     // 自定义类型
  21.     Time _t;
  22. };
  23. int main()
  24. {
  25.     Date d;
  26.     return 0;
  27. }
复制代码
注:类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数即可,好比 Date 类(成员均为内置范例);有资源申请时,析构函数必须写,否则会造成资源走漏,好比 Stack 类
3.3 训练

两个栈实现一个队列
使用 STL 库
  1. #include <stack>
  2. using namespace std;
  3. class MyQueue {
  4. public:
  5.     MyQueue() {
  6.     }
  7.     void push(int x) {
  8.         s1.push(x);
  9.     }
  10.     int pop() {
  11.         int res = peek();
  12.         s2.pop();
  13.         return res;
  14.     }
  15.     int peek() {
  16.         if (s2.empty()) //先判断 s2 是否为空, 若 s2 不为空直接输出 s2 栈顶元素
  17.         {
  18.             while (!s1.empty()) //s2 为空则将 s1 的内容入 s2 栈
  19.             {
  20.                 s2.push(s1.top());
  21.                 s1.pop();
  22.             }
  23.         }
  24.         return s2.top();
  25.     }
  26.     bool empty() {
  27.         return s1.empty() && s2.empty();
  28.     }
  29. private:
  30.     stack<int> s1, s2;
  31. };
复制代码
提交截图

C 自实现栈
  1. #define MAX_LEN 10
  2. typedef int DataType;
  3. class MyStack
  4. {
  5. public:
  6.     MyStack()
  7.         : _array((DataType*)malloc(_capacity * sizeof(DataType)))
  8.     {
  9.         if (nullptr == _array)
  10.         {
  11.             perror("malloc申请空间失败");
  12.             return;
  13.         }
  14.     }
  15.     ~MyStack()
  16.     {
  17.         if (_array) {
  18.             free(_array);
  19.             _array = nullptr;
  20.         }
  21.         
  22.     }
  23.     void push(const DataType& x) {
  24.         _array[_size] = x;
  25.         ++_size;
  26.         if (_size > _capacity)
  27.         {
  28.             _capacity *= 2;
  29.             DataType*  tmpPtr = (DataType*)malloc(sizeof(DataType) * _capacity);
  30.             memcpy(tmpPtr, _array, sizeof(DataType) * _capacity / 2);
  31.             free(_array);
  32.             _array = tmpPtr;
  33.         }
  34.     }
  35.     void pop() {
  36.         --_size;
  37.     }
  38.     int top() {
  39.         return _array[_size - 1];
  40.     }
  41.     bool empty() {
  42.         return _size == 0;
  43.     }
  44. private:
  45.     int _size = 0;
  46.     int _capacity = MAX_LEN;
  47.     DataType* _array; //类型数组
  48. };
  49. class MyQueue {
  50. public:
  51.     MyQueue() {
  52.     }
  53.     void push(int x) {
  54.         s1.push(x);
  55.     }
  56.     int pop() {
  57.         int res = peek();
  58.         s2.pop();
  59.         return res;
  60.     }
  61.     int peek() {
  62.         if (s2.empty()) //先判断 s2 是否为空, 若 s2 不为空直接输出 s2 栈顶元素
  63.         {
  64.             while (!s1.empty()) //s2 为空则将 s1 的内容入 s2 栈
  65.             {
  66.                 s2.push(s1.top());
  67.                 s1.pop();
  68.             }
  69.         }
  70.         return s2.top();
  71.     }
  72.     bool empty() {
  73.         return s1.empty() && s2.empty();
  74.     }
  75. private:
  76.     MyStack s1, s2;
  77. };
复制代码
提交截图

四 拷贝构造函数

4.1 概念

拷贝构造函数
单个形参,该形参是对本类范例对象的引用 ( 一样平常常用 const 修饰 ),用已存在的对象创建新对象
特征
1、拷贝构造函数是构造函数的一个重载
2、拷贝构造函数参数只有一个且必须是范例对象引用(传值方式编译器直接报错,会引发无穷递归调用)
  1. class Date
  2. {
  3. public:
  4.     Date(int year = 1900, int month = 1, int day = 1)
  5.     {
  6.         _year = year;
  7.         _month = month;
  8.         _day = day;
  9.     }
  10.     // Date(const Date& d)   // 正确写法
  11.     Date(const Date& d)   // 错误写法:编译报错,会引发无穷递归
  12.     {
  13.         _year = d._year;
  14.         _month = d._month;
  15.         _day = d._day;
  16.     }
  17.    
  18. private:
  19.     int _year;
  20.     int _month;
  21.     int _day;
  22. };
  23. int main()
  24. {
  25.     Date d1;
  26.     Date d2(d1);
  27.     return 0;
  28. }
复制代码
4.2 默认拷贝构造函数

若未显式定义,编译器会生成默认的拷贝构造函数
注意:编译器生成的默认拷贝构造函数中,内置范例按照字节方式直接拷贝(浅拷贝或值拷贝),而自定义范例是调用其拷贝构造函数完成拷贝
  1. class Time
  2. {
  3. public:
  4.     Time()
  5.     {
  6.         _hour = 1;
  7.         _minute = 1;
  8.         _second = 1;
  9.     }
  10.    
  11.     Time(const Time& t)
  12.     {
  13.         _hour = t._hour;
  14.         _minute = t._minute;
  15.         _second = t._second;
  16.         cout << "Time::Time(const Time&)" << endl;
  17.     }
  18.    
  19. private:
  20.     int _hour;
  21.     int _minute;
  22.     int _second;
  23. };
  24. class Date
  25. {
  26. private:
  27.     // 基本类型(内置类型)
  28.     int _year = 1970;
  29.     int _month = 1;
  30.     int _day = 1;
  31.     // 自定义类型
  32.     Time _t;
  33. };
  34. int main()
  35. {
  36.     Date d1;
  37.     // 用已经存在的 d1 拷贝构造 d2, 此处会调用 Date 类的拷贝构造函数
  38.     // 但 Date 类并没有显式定义拷贝构造函数, 则编译器会给 Date 类生成一个默认的拷贝构造函数
  39.     Date d2(d1);
  40.     return 0;
  41. }
复制代码
注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构造函数必须写,否则就是浅拷贝,如下例
  1. typedef int DataType;
  2. class Stack
  3. {
  4. public:
  5.     Stack(size_t capacity = 10)
  6.     {
  7.         _array = (DataType*)malloc(capacity * sizeof(DataType));
  8.         if (nullptr == _array)
  9.         {
  10.             perror("malloc申请空间失败");
  11.             return;
  12.         }
  13.         _size = 0;
  14.         _capacity = capacity;
  15.     }
  16.    
  17.     void Push(const DataType& data)
  18.     {
  19.         // CheckCapacity();
  20.         _array[_size] = data;
  21.         _size++;
  22.     }
  23.    
  24.     ~Stack()
  25.     {
  26.         if (_array)
  27.         {
  28.             free(_array);
  29.             _array = nullptr;
  30.             _capacity = 0;
  31.             _size = 0;
  32.         }
  33.     }
  34.    
  35. private:
  36.     DataType *_array;
  37.     size_t _size;
  38.     size_t _capacity;
  39. };
  40. int main()
  41. {
  42.     Stack s1;
  43.     s1.Push(1);
  44.     s1.Push(2);
  45.     s1.Push(3);
  46.     s1.Push(4);
  47.     Stack s2(s1);
  48.     return 0;
  49. }
复制代码
将会导致瓦解

4.3 典范调用场景

1、使用已存在对象创建新对象
2、函数参数范例为类范例对象
3、函数返回值范例为类范例对象
  1. class Date
  2. {
  3. public:
  4.     Date(int year, int minute, int day)
  5.     {
  6.         cout << "Date(int,int,int):" << this << endl;
  7.     }
  8.    
  9.     Date(const Date& d)
  10.     {
  11.         cout << "Date(const Date& d):" << this << endl;
  12.     }
  13.    
  14.     ~Date()
  15.     {
  16.         cout << "~Date():" << this << endl;
  17.     }
  18.    
  19. private:
  20.     int _year;
  21.     int _month;
  22.     int _day;
  23. };
  24. Date Test(Date d)
  25. {
  26.     Date temp(d);
  27.     return temp;
  28. }
  29. int main()
  30. {
  31.     Date d1(2022,1,13);
  32.     Test(d1);
  33.     return 0;
  34. }
复制代码
为了提高步调效率,一样平常对象传参时,尽量使用引用范例,返回时根据实际场景,能用引用尽量使用引用(只要是不函数内部栈对象,均可使用引用)
五 赋值运算符重载

5.1 运算符重载

C++为增强代码可读性引入了运算符重载**,**运算符重载是具有特殊函数名的函数
   函数名字为:关键字 operator 后面接需要重载的运算符符号
  函数原型:返回值范例 operator操纵符 ( 参数列表 )
  注意

  • 不能通过连接其他符号来创建新的操纵符:好比operator@
  • 重载操纵符必须有一个类范例参数
  • 用于内置范例的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
  • 作为类成员函数重载时,其形参看起来比操纵数数目少一,因为成员函数的第一个参数为隐蔽的 this
  • .* :: sizeof ?: . 以上5个运算符不能重载
  1. // 全局的 operator==
  2. class Date
  3. {
  4. public:
  5.     Date(int year = 1900, int month = 1, int day = 1)
  6.     {
  7.         _year = year;
  8.         _month = month;
  9.         _day = day;
  10.     }   
  11. //private:
  12.     int _year;
  13.     int _month;
  14.     int _day;
  15. };
  16. //全局运算符重载需要成员变量是公有的, 不能保证封装性, 如何解决 ?
  17. //可以用友元解决或重载成成员函数
  18. bool operator==(const Date& d1, const Date& d2)
  19. {
  20.     return d1._year == d2._year
  21.         && d1._month == d2._month
  22.         && d1._day == d2._day;
  23. }
  24. void Test ()
  25. {
  26.     Date d1(2018, 9, 26);
  27.     Date d2(2018, 9, 27);
  28.     cout << (d1 == d2) << endl;
  29. }
复制代码
如下
  1. class Date
  2. {
  3. public:
  4.     Date(int year = 1900, int month = 1, int day = 1)
  5.     {
  6.         _year = year;
  7.         _month = month;
  8.         _day = day;
  9.     }
  10.     //bool operator == (Date* this, const Date& d2)
  11.     //注意左操作数是 this, 指向调用函数的对象
  12.     bool operator==(const Date& d2)
  13.     {
  14.         return _year == d2._year;
  15.         && _month == d2._month
  16.             && _day == d2._day;
  17.     }
  18.    
  19. private:
  20.     int _year;
  21.     int _month;
  22.     int _day;
  23. };
复制代码
5.2 赋值运算符重载

1、赋值运算符重载格式
参数范例:const T&,传递引用提高传参效率
返回值范例:T& 返回引用提高效率,有返回值为了支持连续赋值
检测是否本身给本身赋值
返回 *this 要复合连续赋值的含义
  1. class Date
  2. {
  3. public :
  4.     Date(int year = 1900, int month = 1, int day = 1)
  5.     {
  6.         _year = year;
  7.         _month = month;
  8.         _day = day;
  9.     }
  10.     Date (const Date& d)
  11.     {
  12.         _year = d._year;
  13.         _month = d._month;
  14.         _day = d._day;
  15.     }
  16.     Date& operator=(const Date& d)
  17.     {
  18.         if(this != &d)
  19.         {
  20.             _year = d._year;
  21.             _month = d._month;
  22.             _day = d._day;
  23.         }
  24.         return *this;
  25.     }
  26.    
  27. private:
  28.     int _year ;
  29.     int _month ;
  30.     int _day ;
  31. };
复制代码
2、赋值运算符只能重载为类成员函数不能重载为全局函数
  1. class Date
  2. {
  3. public:
  4.     Date(int year = 1900, int month = 1, int day = 1)
  5.     {
  6.         _year = year;
  7.         _month = month;
  8.         _day = day;
  9.     }
  10.     int _year;
  11.     int _month;
  12.     int _day;
  13. };
  14. // 赋值运算符重载为全局函数, 注意没有 this 指针, 需要给两个参数
  15. Date& operator=(Date& left, const Date& right)
  16. {
  17.     if (&left != &right)
  18.     {
  19.         left._year = right._year;
  20.         left._month = right._month;
  21.         left._day = right._day;
  22.     }
  23.     return left;
  24. }
  25. // 编译失败:
  26. // error C2801: “operator =”必须是非静态成员
复制代码
原因:赋值运算符如果不显式实现,编译器会生成一个默认的。此时再在类外实现一个全局赋值运算符重载,和编译器生成的默认赋值运算符重载冲突,故赋值运算符重载只能是类的成员函数
C++ PRIME 第五版 500 页

3、默认赋值运算符重载
没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。注意:内置范例成员变量是直接赋值的,而自定义范例成员变量需要调用对应类的赋值运算符重载完成赋值(和类似拷贝构造)
5.3 前置++ 和后置++ 重载

  1. class Date
  2. {
  3. public:
  4.     Date(int year = 1900, int month = 1, int day = 1)
  5.     {
  6.         _year = year;
  7.         _month = month;
  8.         _day = day;
  9.     }
  10.     // 前置++: 返回 +1 之后的结果
  11.     // 注意: this 指向的对象函数结束后不会销毁, 以引用方式返回提高效率
  12.     Date& operator++()
  13.     {
  14.         _day += 1;
  15.         return *this;
  16.     }
  17.    
  18.     // 后置++
  19.     // 前置++ 和后置++ 都是一元运算符, 为了让前置++ 与后置++ 形成能正确重载, C++ 规定后置++ 重载时多增加一个 int 类型参数, 但调用函数时该参数不用传递,编译器自动传递
  20.     // 注意: 后置++ 是先使用后 +1, 因此需要返回 +1 之前的旧值, 故需在实现时需要先将 this 保存一份, 然后给 this + 1. 而 temp 是临时对象, 因此只能以值的方式返回, 不能返回引用
  21.     Date operator++(int)
  22.     {
  23.         Date temp(*this);
  24.         _day += 1;
  25.         return temp;
  26.     }
  27. private:
  28.     int _year;
  29.     int _month;
  30.     int _day;
  31. };
  32. int main()
  33. {
  34.     Date d;
  35.     Date d1(2022, 1, 13);
  36.     d = d1++;    // d: 2022,1,13   d1:2022,1,14
  37.     d = ++d1;    // d: 2022,1,15   d1:2022,1,15
  38.     return 0;
  39. }
复制代码
六 const 成员

将 const 修饰的成员函数称之为 const 成员函数,const 修饰类成员函数,实际修饰该成员函数隐含的 this 指针,表明在该成员函数中不能对类的任何成员举行修改

针对以下代码
  1. class Date
  2. {
  3. public:
  4.     Date(int year, int month, int day)
  5.     {
  6.         _year = year;
  7.         _month = month;
  8.         _day = day;
  9.     }
  10.    
  11.     void Print()
  12.     {
  13.         cout << "Print()" << endl;
  14.         cout << "year:" << _year << endl;
  15.         cout << "month:" << _month << endl;
  16.         cout << "day:" << _day << endl;
  17.     }
  18.    
  19.     void Print() const
  20.     {
  21.         cout << "Print() const" << endl;
  22.         cout << "year:" << _year << endl;
  23.         cout << "month:" << _month << endl;
  24.         cout << "day:" << _day << endl;
  25.     }
  26.    
  27. private:
  28.     int _year; // 年
  29.     int _month; // 月
  30.     int _day; // 日
  31. };
  32. void Test()
  33. {
  34.     Date d1(2022,1,13);
  35.     d1.Print();
  36.     const Date d2(2022,1,13);
  37.     d2.Print();
  38. }
复制代码
回答下列问题
1、const 对象可以调用非 const 成员函数吗
不可以,因为 const 对象的成员变量无法修改,this 指针的范例为 const type*
2、非 const 对象可以调用 const 成员函数吗
可以
3、const 成员函数内可以调用其它的非 const 成员函数吗
不可以
4、非 const 成员函数内可以调用其它的 const 成员函数吗
可以, const 成员函数不会修改成员变量,非 const 成员函数可能会修改,属于权限放大
七 取所在及 const 取所在操纵符重载

这两个默认成员函数一样平常不消重新定义 ,编译器默认会生成
  1. class Date
  2. {
  3. public :
  4.     Date* operator&()
  5.     {
  6.         return this;
  7.     }
  8.    
  9.     const Date* operator&() const
  10.     {
  11.         return this;
  12.     }
  13.    
  14. private :
  15.     int _year; // 年
  16.     int _month; // 月
  17.     int _day; // 日
  18. };
复制代码
这两个运算符一样平常不需要重载,使用编译器生成的默认取所在的重载即可。只有特殊情况,才需要重载,好比想让外部无法获取到该类对象所在时
  1. class Date
  2. {
  3. public :
  4.     Date* operator&()
  5.     {
  6.         return nullptr;
  7.     }
  8.    
  9.     const Date* operator&() const
  10.     {
  11.         return nullptr;
  12.     }
  13.    
  14. private :
  15.     int _year; // 年
  16.     int _month; // 月
  17.     int _day; // 日
  18. };
复制代码
八 日期类的实现

给出 Date 类如下头文件,实现 Date.cpp
  1. class Date
  2. {
  3. public:
  4.     // 获取某年某月的天数
  5.     int GetMonthDay(int year, int month)
  6.     {
  7.         static int days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  8.         int day = days[month];
  9.         if (month == 2
  10.             && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
  11.         {
  12.             day += 1;
  13.         }
  14.         return day;
  15.     }
  16.     // 全缺省的构造函数
  17.     Date(int year = 1900, int month = 1, int day = 1);
  18.     // 拷贝构造函数
  19.     // d2(d1)
  20.     Date(const Date& d);
  21.     // 赋值运算符重载
  22.     // d2 = d3 -> d2.operator=(&d2, d3)
  23.     const Date& operator=(const Date& d);
  24.     // 析构函数
  25.     ~Date();
  26.     // 日期+=天数
  27.     Date& operator+=(int day);
  28.     // 日期+天数
  29.     Date operator+(int day) const;
  30.     // 日期-天数
  31.     Date operator-(int day) const;
  32.     // 日期-=天数
  33.     Date& operator-=(int day);
  34.     // 前置++
  35.     Date& operator++();
  36.     // 后置++
  37.     Date operator++(int);
  38.     // 后置--
  39.     Date operator--(int);
  40.     // 前置--
  41.     Date& operator--();
  42.     // >运算符重载
  43.     bool operator>(const Date& d) const;
  44.     // ==运算符重载
  45.     bool operator==(const Date& d) const;
  46.     // >=运算符重载
  47.     bool operator >= (const Date& d) const;
  48.     // <运算符重载
  49.     bool operator < (const Date& d) const;
  50.     // <=运算符重载
  51.     bool operator <= (const Date& d) const;
  52.     // !=运算符重载
  53.     bool operator != (const Date& d) const;
  54.     // 日期-日期 返回天数
  55.     int operator-(const Date& d) const;
  56. private:
  57.     int _year;
  58.     int _month;
  59.     int _day;
  60. };
复制代码
代码实现
  1. #include "Date.h"
  2. // 全缺省的构造函数
  3. Date::Date(int year = 1900, int month = 1, int day = 1) {}
  4. // 拷贝构造函数
  5. // d2(d1)
  6. Date::Date(const Date& d) {}
  7. // 赋值运算符重载
  8. // d2 = d3 -> d2.operator=(&d2, d3)
  9. const Date& Date::operator=(const Date& d)
  10. {
  11.         _year = d._year;
  12.         _month = d._month;
  13.         _day = d._day;
  14.         return *this;
  15. }
  16. // 析构函数
  17. Date::~Date() {}
  18. // 日期+=天数
  19. Date& Date::operator+=(int day)
  20. {
  21.         if (day < 0) return *this -= day;
  22.         _day += day;
  23.         while(_day > GetMonthDay(_year,_month))
  24.         {
  25.                 _day -= GetMonthDay(_year, _month);
  26.                 _month++;
  27.                 if (_month == 13)
  28.                 {
  29.                         _year++;
  30.                         _month = 1;
  31.                 }
  32.         }
  33.         return *this;
  34. }
  35. // 日期-=天数
  36. Date& Date::operator-=(int day)
  37. {
  38.         if (day < 0) return *this += -day;
  39.         _day -= day;
  40.         while (_day <= 0)
  41.         {
  42.                 _month--;
  43.                 if (_month == 0)
  44.                 {
  45.                         _year--;
  46.                         _month = 12;
  47.                 }
  48.                 _day += GetMonthDay(_year, _month);
  49.         }
  50.         return *this;
  51. }
  52. // 日期+天数
  53. Date Date::operator+(int day) const
  54. {
  55.         Date ret(*this);
  56.         ret += day;
  57.         return ret;
  58. }
  59. // 日期-天数
  60. Date Date::operator-(int day) const
  61. {
  62.         Date ret(*this);
  63.         ret -= day;
  64.         return ret;
  65. }
  66. // 前置++
  67. Date& Date::operator++()
  68. {
  69.         *this += 1;
  70.         return *this;
  71. }
  72. // 后置++
  73. Date Date::operator++(int)
  74. {
  75.         Date ret(*this);
  76.         ret += 1;
  77.         return ret;
  78. }
  79. // 前置--
  80. Date& Date::operator--()
  81. {
  82.         *this -= 1;
  83.         return *this;
  84. }
  85. // 后置--
  86. Date Date::operator--(int)
  87. {
  88.         Date ret(*this);
  89.         ret -= 1;
  90.         return ret;
  91. }
  92. // > 运算符重载
  93. bool Date::operator>(const Date& d) const
  94. {
  95.         if (_year > d._year) return true;
  96.         else if (_year < d._year) return false;
  97.         else
  98.         {
  99.                 if (_month > d._month) return true;
  100.                 else if (_month < d._month) return false;
  101.                 else
  102.                 {
  103.                         if (_day > d._day) return true;
  104.                         else if (_day < d._day) return false;
  105.                 }
  106.         }
  107.         return false;
  108. }
  109. // == 运算符重载
  110. bool Date::operator==(const Date& d) const
  111. {
  112.         return _year == d._year &&
  113.                    _month == d._month &&
  114.                    _day == d._year;
  115. }
  116. // < 运算符重载
  117. bool Date::operator < (const Date& d) const
  118. {
  119.         if (_year < d._year) return true;
  120.         else if (_year > d._year) return false;
  121.         else
  122.         {
  123.                 if (_month < d._month) return true;
  124.                 else if (_month > d._month) return false;
  125.                 else
  126.                 {
  127.                         if (_day < d._day) return true;
  128.                         else if (_day > d._day) return false;
  129.                 }
  130.         }
  131.         return false;
  132. }
  133. // >=运算符重载
  134. bool Date::operator >= (const Date& d) const
  135. {
  136.         if (*this < d) return false;
  137.         else return true;
  138. }
  139. // <=运算符重载
  140. bool Date::operator <= (const Date& d) const
  141. {
  142.         if (*this > d) return false;
  143.         else return true;
  144. }
  145. // !=运算符重载
  146. bool Date::operator != (const Date& d) const
  147. {
  148.         if (*this == d) return false;
  149.         else return true;
  150. }
  151. // 日期-日期 返回天数
  152. int Date::operator-(const Date& d) const
  153. {
  154.         int status = 1;
  155.         Date max = *this;
  156.         Date min = d;
  157.         if (max < min)
  158.         {
  159.                 max = d;
  160.                 min = *this;
  161.                 status = -1;
  162.         }
  163.         int day = 0;
  164.         while (min < max)
  165.         {
  166.                 ++min, ++day;
  167.         }
  168.         return status * day;
  169. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

民工心事

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表