C++拷贝构造函数和运算符重载--3

简介: C++拷贝构造函数和运算符重载--3

C++拷贝构造函数和运算符重载--2

https://developer.aliyun.com/article/1424586

二,运算符重载

引入:


       在内置类型中,系统给我们自动定义了很大运算符,如:+、-、*、/、++、--、>等。这些内置类型和内置类型运算符的使用都是系统定义好的,可直接使用。现在问题来了,自定义类型要想使用这些运算符又当如何?由于自定义类型是我们自己定义的,系统不知道其结构,所以无法直接供我们使用,但C++为了增强代码的可读性引入了运算符重载的概念,可让自定义类型也使用这些运算符。运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。


运算符重载的定义:


       函数名:关键字operator后面接需要重载的运算符符号。


       函数原型:返回值类型 operator操作符(参数列表)。


这里有以下5个注意:


       1,不能通过连接其他符号来创建新的操作符:比如operator@


       2,重载操作符必须有一个类类型参数


       3,用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其+本身的含义


       4,作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this指针。


       5,“ .*    ::    sizeof    ?:    . ” 注意这5个运算符不能重载。这个经常在笔试选择题中出现。


在类的内部定义


第一个参数为this指针
// '='操作符,返回类型为类类型Date的引用
Date& operator=(const Date& d);
Date& Date::operator=(const Date& d);//此种情况是在类中声明,在外部实现,用限定符说明是类对象中的成员函数
// "+="操作符,返回类型为类类型Date的引用
Date& operator+=(int day);
Date& Date::operator+=(int day);//此种情况是在类中声明,在外部实现,用限定符说明是类对象中的成员函数
// '+'操作符,返回类型为类类型Date的引用
Date operator+(int day);
Date Date::operator+(int day);//此种情况是在类中声明,在外部实现,用限定符说明是类对象中的成员函数
// '-'操作符,返回类型为类类型Date的引用
Date operator-(int day);
Date Date::operator-(int day);//此种情况是在类中声明,在外部实现,用限定符说明是类对象中的成员函数
// "-="操作符,返回类型为类类型Date的引用
Date& operator-=(int day);
Date& Date::operator-=(int day);//此种情况是在类中声明,在外部实现,用限定符说明是类对象中的成员函数


在类的外部定义


没有默认参数,需要把类写入形参中
// "+="操作符,返回类型为类类型Date的引用
Date& operator+=(const Date& d1, int day);
// '+'操作符,返回类型为类类型Date的引用
Date operator+(const Date& d1, int day);
// '-'操作符,返回类型为类类型Date的引用
Date operator-(const Date& d1, int day);
// "-="操作符,返回类型为类类型Date的引用
Date& operator-=(const Date& d1, int day);

运用细节演示:


       (1)首先,我们先对“ >,<,>=,<=,==,!= ”这几个简单运算符在类对象内定义进行演示和解说。


#include <iostream>
#include <assert.h>
using namespace std;
//再次提醒一下,类对象中的成员函数第一个默认参数为this,且指向此对象,下面运用时就不做说明
class Date
{
public:
  // 全缺省的构造函数
  Date(int year = 1900, int month = 1, int day = 1)
  {
  _year = year;
  _month = month;
  _day = day;
  }
  // ==运算符重载
  bool operator==(const Date& d)
  {
  return _year == d._year &&
    _month == d._month &&
    _day == d._day;
  }
  // !=运算符重载
  bool operator != (const Date& d)
  {
  return !(*this == d);
  }
  // >运算符重载
  bool operator>(const Date& d)
  {
  if (_year > d._year)
    return true;
  else if (_year == d._year && _month > d._month)
    return true;
  else if (_year == d._year && _month == d._month && _day > d._day)
    return true;
  return false;
  }
  // >=运算符重载
  bool operator >= (const Date& d)
  {
  return *this > d || *this == d;
  }
  // <运算符重载
  bool operator < (const Date& d)
  {
  if (_year < d._year)
    return true;
  else if (_year == d._year && _month < d._month)
    return true;
  else if (_year == d._year && _month == d._month && _day < d._day)
    return true;
  return false;
  }
  // <=运算符重载
  bool operator <= (const Date& d)
  {
  return *this < d || *this == d;
  }
private:
  int _year;
  int _month;
  int _day;
};
int main()
{
  Date d1;
  Date d2(2023, 10, 16);
  cout << (d1 > d2) << endl;//d1 > d2等效于d1.operator>(d2),这两个表达的意思一样
  cout << d1.operator>(d2) << endl;
  return 0;
}

       在上面代码中要说明的是在运算符表示过程中,我们即可用函数来表示运算符的含义,也可直使用运算符的形式表示含义。


在上面的运算符函数中:
d1 > d2等效于d1.operator(d2)
d1 == d2等效于d1.operator(d2)
上面的输出流中之所以(d1 > d2)用括号括起来是因为“ << ”操作符的运算级别高,会先与之运算。


       (2)接下来我们对“ +,-,+=,-= ”这几个简单运算符在类对象内定义进行演示和解说。


#include <iostream>
#include <assert.h>
using namespace std;
class Date
{
public:
  // 获取某年某月的天数
  int GetMonthDay(int year, int month)
  {
  assert(year >= 1 && (month >= 1 && month <= 12));
  int MonthDays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  if ((month == 2) && ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)))
    return 29;
  return MonthDays[month];
  }
  // 全缺省的构造函数
  Date(int year = 1900, int month = 1, int day = 1)
  {
  _year = year;
  _month = month;
  _day = day;
  }
  // 日期-天数
  Date operator-(int day)
  {
  _day -= day;
  while (_day < 0) {
    if (_month == 1) {
    _year--;
    if (_year < 0) {
      perror("Date Count Error:");
      exit(-1);
    }
    _month = 12;
    }
    else {
    _month--;
    }
    _day += GetMonthDay(this->_year, this->_month);
  }
  return *this;
  }
  // 日期-=天数
  Date& operator-=(int day)
  {
  Date DateCopy(*this);
  //用临时对象返回,相当于函数的返回,需要有个对象去接收,而改变的只是临时对象
  //像直接使用类d1 -= 5,表达的只是此函数的功能,d1的值不会改变,若是d1 = d1 -= 5将会改变
  //DateCopy = DateCopy.operator-(day);
  //return DateCopy;
  //this指针直接指向的是此对象(即此类),用this指针来改变相当于直接改变了d1,类似于达到了改变d1的效果
  *this = DateCopy.operator-(day);
  return *this;
  }
  // 日期+=天数
  Date& operator+=(int day)
  {
  _day += day;
  while (_day > GetMonthDay(this->_year, this->_month)) {
    _day -= GetMonthDay(this->_year, this->_month);
    _month++;
    if (_month > 12) {
    _year++;
    _month -= 12;
    }
  }
  return *this;
  }
  // 日期+天数
  Date operator+(int day)
  {
  Date DateCopy(*this);
  DateCopy.operator+=(day);
  return DateCopy;
  }
  // 日期-日期 返回天数
  int operator-(const Date& d)
  {
  int YearDay = 0, MonthDay = 0, Day = _day - d._day;
  while (--_month) {
    MonthDay += GetMonthDay(_year, _month);
  }
  int month = d._month;
  while (--month) {
    MonthDay -= GetMonthDay(d._year, month);
  }
  _year--;
  int year = d._year - 1;
  for (int YearCount = _year - year; YearCount > 0; YearCount--) {
    YearDay += 365;
    if ((_year % 400 == 0) || ((_year % 4 == 0) && (_year % 100 != 0)))
    YearDay += 1;
    _year--;
  }
  return YearDay + MonthDay + Day;
  }
  void Print() {
  cout << _year << "/" << _month << "/" << _day << endl;
  }
private:
  int _year;
  int _month;
  int _day;
};
int main()
{
  Date d1(2023, 10, 16);
  Date d2;
  //+=和+运算符重载
  //这里要说明的是,由于"+="没有返回值,所以在函数对象内部改变的时候一定要用this指针来改变,this指针指向d1
  d1 += 365;
  cout << "d1重载d1+=365: ";
  d1.Print();
  d2 = d1 + 23;
  cout << "d2重载d2=d1+23: ";
  d2.Print();
  //-=和-的运算符重载
  //"-="运算符与"+="同理
  d1 -= 365;
  cout << "d1重载d1-=365: ";
  d1.Print();
  d2 = d1 - 365;
  cout << "d2重载d2=d1-365: ";
  d2.Print();
  //日期-日期的运用
  cout << "d2-d1: " << d2 - d1 << endl;
  return 0;
}

       这里要注意的是函数的返回类型,“ +=,-= ”运算一般是不需要返回类型的,所以在内部实现要用this访问,从而间接实现原对象的运算。“ +,- ”操作符要有返回类型去接收,可直接返回临时对象。


C++拷贝构造函数和运算符重载--4 https://developer.aliyun.com/article/1424601?spm=a2c6h.13148508.setting.29.214f4f0emw3QR7

相关文章
|
1天前
|
测试技术 C++
C++|运算符重载(3)|日期类的计算
C++|运算符重载(3)|日期类的计算
|
1天前
|
C语言 C++
C++|运算符重载(2)|运算符重载的方法与规则
C++|运算符重载(2)|运算符重载的方法与规则
|
2天前
|
编译器 C++
C++|运算符重载(1)|为什么要进行运算符重载
C++|运算符重载(1)|为什么要进行运算符重载
|
3天前
|
编译器 C语言 C++
【C++从练气到飞升】05---运算符重载(二)
【C++从练气到飞升】05---运算符重载(二)
|
3天前
|
编译器 C++
【C++从练气到飞升】05---运算符重载(一)
【C++从练气到飞升】05---运算符重载(一)
|
3天前
|
存储 编译器 C++
【C++从练气到飞升】04---拷贝构造函数
【C++从练气到飞升】04---拷贝构造函数
|
3天前
|
编译器 C++
【C++】类与对象(运算符重载、const成员、取地址重载)
【C++】类与对象(运算符重载、const成员、取地址重载)
14 2
|
3天前
|
存储 编译器 对象存储
【C++】类与对象(构造函数、析构函数、拷贝构造函数、常引用)
【C++】类与对象(构造函数、析构函数、拷贝构造函数、常引用)
7 0
|
3天前
|
编译器 C++ 索引
【C++类和对象】拷贝构造与赋值运算符重载(下)
【C++类和对象】拷贝构造与赋值运算符重载
|
3天前
|
存储 编译器 C++
【C++类和对象】拷贝构造与赋值运算符重载(上)
【C++类和对象】拷贝构造与赋值运算符重载