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:
- Noções básicas : Classes e Objetos (envolvendo os três principais recursos do C++, etc.);
- STL : Aprenda a usar as bibliotecas relacionadas ao STL fornecidas pelo C++ ;
- 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:
Diretório de artigos
- Descrição do artigo da série
- Prefácio
- 1. Sobrecarga de operador aritmético (atribuição) C++
- 2. Incremento automático e sobrecarga do operador de decremento em C++
- Artigos relacionados
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)
2.1 Ideias de design
Portanto, precisamos sobrecarregar os nossos operadores!
由于 + 或 - 可以基于 += 或 -= 来实现
, portanto o autor dá prioridade à sua implementação+= / -= 的重载
!
Implemente ideias de design:
参数问题
: Obviamente você precisa passar alguns dias para operação recursiva. O valor não precisa ser alterado, portanto pode ser modificado com const.日期迭代计算问题
: 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 -=
设计思路(注意点):
- 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!
- Parâmetros: Extrapole o número de dias passados.
返回值:日期的引用!
其他细节见注释!
+= 运算符重载(实现如下)
/* += 赋值运算符重载 */
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
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;
}
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;
}
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!
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
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]