[C++ Basics: 25]: [Modelo importante] Sobrecarga de operador aritmético (atribuição) C++ e sobrecarga de operador de incremento e decremento automático [Tome a classe de data Date como exemplo]

Descrição do artigo da série

Esta série de artigos relacionados a C++ é apenas para notas de estudo do autor, e usarei meu próprio entendimento para registrar o estudo! A série de aprendizagem C++ será dividida em três estágios: básico, STL e estruturas de dados e algoritmos avançados . Os principais conteúdos relevantes são os seguintes:

  1. Noções básicas : Classes e Objetos (envolvendo os três principais recursos do C++, etc.);
  2. STL : Aprenda a usar as bibliotecas relacionadas ao STL fornecidas pelo C++ ;
  3. Estruturas de dados e algoritmos de alta ordem : implemente manualmente sua própria biblioteca STL e projete e implemente estruturas de dados de alta ordem , como árvore B, árvore B+, árvore vermelha e preta, etc.

Conjunto de estudo:



Prefácio

  • O aprendizado básico das aulas atingiu um determinado estágio, então o conteúdo que o autor irá compartilhar com vocês nos artigos recentes é: " 运算符重载小专题"! Atualmente atualizado:, 关系运算符的重载(点击跳转)resolveu 输入输出运算符重载(点击跳转)o problema de comparação e entrada e saída de tipos/objetos customizados!
  • Neste artigo, o autor compartilhará com você 自定义类型 / 对象o problema de cálculo de! Isto é: 自增自减运算符重载及算术运算符重载.

1. Sobrecarga de operador aritmético (atribuição) C++

1. Descrição

Este artigo tomará +、-、+=、-=como exemplo para projetar e implementar a sobrecarga de operadores aritméticos (atribuição)! [Nota: Na descrição anterior da sobrecarga do operador, foi mencionado que a sobrecarga do operador não pode alterar seu próprio significado!


2. Sobrecarga do operador += / -= [tome a classe de calendário Data como exemplo]

符号含义

  • +=: Operador de adição e atribuição, atribui o resultado da adição do operando direito ao operando esquerdo ao operando esquerdo!
  • -=: Operador de subtração AND de atribuição, atribui o resultado da subtração do operando direito do operando esquerdo para o operando esquerdo

Para nossa classe de data Date, as interfaces geralmente fornecidas incluem: Calcule o problema da data adicionando ou subtraindo quantos dias após a data atual!
Neste momento surgirão situações de cálculo como: 2023-6-16 += ou + 15 dias! Obviamente é impossível realizar cálculos utilizando os operadores originais! (Como mostrado abaixo)

Insira a descrição da imagem aqui


2.1 Ideias de design

Portanto, precisamos sobrecarregar os nossos operadores! 由于 + 或 - 可以基于 += 或 -= 来实现, portanto o autor dá prioridade à sua implementação += / -= 的重载!


Implemente ideias de design:

  1. 参数问题: Obviamente você precisa passar alguns dias para operação recursiva. O valor não precisa ser alterado, portanto pode ser modificado com const.
  2. 日期迭代计算问题: Devido à mudança de data envolvida, nós 需要考虑的每个月的天数问题! E 可能出现闰年二月的情形!

2.2 Solução: Problema do Ano Bissexto (Introdução às Regras de Cálculo e Origem)

Sobre: ​​problema do ano bissexto!

  • 判断闰年的方式(1582年后的计算准则):该年可以被 400 整除 或 概念可以被 4 整除但不能被 100 整除,如:1900年不是闰年!

Quanto à origem dos anos bissextos: (As regras de cálculo acima para anos bissextos são aquelas posteriores a 1582!)

  • As regras bissextas do calendário gregoriano desde 1582:
  • Ano bissexto comum: se o ano do calendário gregoriano for um múltiplo de 4 e não um múltiplo de 100, é um ano bissexto (como 2004, 2020, etc. são anos bissextos).
  • Ano bissexto do século: O ano do calendário gregoriano é cem e deve ser um múltiplo de 400 para ser um ano bissexto (por exemplo, 1900 não é um ano bissexto, mas 2000 é um ano bissexto).
  • A convenção antes de 1582: há um ano bissexto a cada quatro anos; se A (número positivo) no ano A DC pode ser dividido por 4, então é um ano bissexto; se B (número positivo) no ano B BC divide 4 e o resto é 1, então é um ano bissexto. Também é um ano bissexto.

Implementação da função de julgamento de ano bissexto (como segue):

  • Parâmetros: ano
  • Valor de retorno: sim/não
/* 闰年判断 */
bool IsLeapYear(int year) {
    
    
	return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}

2.3 Dias no mês

Para facilitar o cálculo, o autor desenhou a aquisição do número de dias do mês em função!


Idéias de design:

  • Parâmetros: ano, mês
  • Valor de retorno: tipo int (número de dias)
  • Processamento especial: Fevereiro é definido como 28 dias por padrão. Se for encontrado um ano bissexto, o valor de retorno será +1;
  • 优化处理:由于获取月份天数可能使用频率较高,建议使用数组存储数据(设计如下:注意注释解释),并设定为静态数组!(避免每次调用函数新建数组的性能开销!)。

O código é implementado da seguinte forma:

/* 获取月份天数 */
int GetMonthDay(int year, int month) {
    
    
	/* 设置为静态数组提升效率 */
	/* 数组大小设置为 13 ,即为了直接使用 days[month] 访问到数据 */
	static int days[13] = {
    
     0,31,28,31,30,31,30,31,31,30,31,30,31 };
	
	if (month == 2 && IsLeapYear(year)) {
    
    
		return days[month] + 1;
	}
	return days[month];
}

2.4 Projeto de sobrecarga e implementação do operador += ou -=

设计思路(注意点):


  1. A ideia básica: sempre somar/diminuir o número de dias para calcular a data. Durante o processo, preste atenção ao julgar a mudança de mês e a mudança de ano!
  2. Parâmetros: Extrapole o número de dias passados.
  3. 返回值:日期的引用!
  4. 其他细节见注释!

+= 运算符重载(实现如下)

/* += 赋值运算符重载 */
Date& Date::operator += (const int day) {
    
    
	_day += day;									/* 直接递增天数 */
	while (_day > GetMonthDay(_year, _month)) {
    
    		/* 日期“合法性”判断 */
		/* 若:天数大于本月的固定天数,则 天数 - 本月天数,并将月份 + 1 */
		_day -= GetMonthDay(_year, _month);			/* 天数更跌 */
		_month += 1;								/* 月份更迭 */
		if (_month == 13) {
    
    							/* 年份更迭 */
			_month = 1;
			_year++;
		}
	}
	return *this;
}

-= 运算符重载(实现如下)

Date& Date::operator -= (const int day) {
    
    
	_day -= day;
	while (_day < 1) {
    
    								/* 判断天数合法性 */
		if (_month == 1) {
    
    							/* 特殊点:年份更迭 */
			_month = 13;							/* 注意此处:13,为的是后续统一的月份更迭计算 */
			_year--;
		}
		_day += GetMonthDay(_year, _month - 1);
		_month--;
	}
	return *this;
}

2.5 Resultados da legenda do teste

Insira a descrição da imagem aqui


3. + ou - sobrecarga do operador

Combinado com o que foi mencionado no artigo anterior para melhorar a reutilização do código, você pode usar diretamente o += ou -= existente para implementar os pontos-chave do operador + ou -!

3.1 Projeto de sobrecarga, implementação e teste do operador +

+ 运算符重载(实现如下,注意注释提示)

  • 注意返回值:不是引用!
/* 
	在该函数中,不会去修改 Date 对象本身,
	而是返回一个新的对象,
	函数外部可以赋值给原对象或新对象!
*/
Date Date::operator+(const int day) const		
{
    
    
	// Date ret(*this);			/* 拷贝构造 */
	Date ret = *this;			
	ret += day;
	return ret;
}

Insira a descrição da imagem aqui


3.2 - Projeto, implementação e testes de sobrecarga do operador

+ 运算符重载(实现如下,注意注释提示)

  • 注意返回值:不是引用!
/* 
	在该函数中,不会去修改 Date 对象本身,
	而是返回一个新的对象,
	函数外部可以赋值给原对象或新对象!
*/
Date Date::operator-(const int day) const		
{
    
    
	// Date ret(*this);			/* 拷贝构造 */
	Date ret = *this;			
	ret -= day;
	return ret;
}

Insira a descrição da imagem aqui


4. Sobre *, /, *=, /= design e implementação de sobrecarga

  • Quanto ao desenho e implementação da sobrecarga de *, /, *=, /=, conforme conteúdo anterior, basta seguir o exemplo!

2. Incremento automático e sobrecarga do operador de decremento em C++

1. Compreensão básica

Em C/C++, podemos usar ++ / --para realizar operações de incremento e decremento nas variáveis ​​de dados que definimos! Esses dois operadores podem ser descritos como um pesadelo para os recém-chegados aprenderem, especialmente nas provas finais de estudantes universitários, que não têm significado prático na avaliação da combinação de operadores de incremento e decremento. [O uso básico é mostrado na imagem abaixo!


Em estudos anteriores você já deve ter ouvido mais ou menos: 前置自增自减 效率高于 后置自增自减. [Claro, quase não deve haver diferença nos compiladores atuais e já foi otimizado]


Sabe-se que 自增自减运算符分为:前置 和 后置a principal diferença é:

  • Pré-posicionamento significa: dar prioridade à sua própria operação antes de participar de outras operações;
  • A posposição é: primeiro participe de outras operações e depois realize sua própria operação!

Insira a descrição da imagem aqui


2. Implementação de sobrecarga de operadores de autoincremento e autodecremento

Front-end e traseira ++ / --No uso real, escrevemos a diferença entre front-end e traseira, mas o que devemos fazer quando sobrecarregar?

  • 函数写法:使用函数重载!
  • 重载函数的区分方式: Use um parâmetro para distinguir ! 方案:前置使用无参形式,后置使用含参形式[ Nota: Após a implementação real, não precisamos exibir o parâmetro passado no processo de pós-implementação! O compilador identificará automaticamente os parâmetros distintivos da sobrecarga do operador de incremento automático e decremento automático]
  • 函数返回值:对象本身(引用返回)

O código de design é o seguinte (observe a reutilização do código):

2.1 Implementação de sobrecarga de operador com prefixo ++ ou –

  • 前置 ++ ,即先 +1 再返回!
  • 前置 -- ,即先 -1 再返回!
/* 前置 ++ */
Date& Date::operator++()
{
    
    
	return *(this + 1);
}

/* 前置 -- */
Date& Date::operator--()
{
    
    
	return *(this - 1);
}

2.2 Postfix ++ ou – implementação de sobrecarga de operador

  • 后置 ++ ,即先返回,再运算!(Com a ajuda de: objetos temporários)
  • 后置 -- ,即先返回,再运算!(Com a ajuda de: objetos temporários)
/* 后置 ++ */
Date& Date::operator++(int)
{
    
    
	Date ret(*this);
	*this += 1;
	return ret;
}

/* 后置 -- */
Date& Date::operator--(int)
{
    
    
	Date ret(*this);
	*this += 1;
	return ret;
}

2.3 Legenda do resultado do teste

Insira a descrição da imagem aqui


Artigos relacionados

1. [C++ Basics Chapter: 21]: amigo Amigos fizeram quatro perguntas: O que é um amigo? Classe amigo? Função amigo? Quando usar amigos?
2. [C++ Basics: 22]: Objetos Const e funções/métodos de membros const de classes e problemas comuns envolvendo const em classes!
3. [C++ Basics: 23]: [Modelo importante] Design e implementação de sobrecarga de operador relacional: [ > , < , >= , <= , != , == ] sobrecarga [tomando a classe Date time como exemplo]


Acho que você gosta

Origin blog.csdn.net/weixin_53202576/article/details/131215397
Recomendado
Clasificación