Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Aprenda Sobrecarga de Operadores | Visão Geral do Polimorfismo
C++ Poo
course content

Conteúdo do Curso

C++ Poo

C++ Poo

1. Fundamentos de POO em C++
2. Construtores e Destrutores
3. Visão Geral do Encapsulamento
4. Visão Geral de Herança
5. Visão Geral do Polimorfismo

book
Sobrecarga de Operadores

Sobrecarga de operadores é um recurso poderoso em linguagens de programação orientadas a objetos que permite redefinir o comportamento dos operadores para classes definidas pelo usuário. Ao sobrecarregar operadores, é possível fornecer implementações personalizadas para operações envolvendo objetos da sua class, tornando o código mais intuitivo e expressivo.

Sintaxe da sobrecarga de operadores

A sobrecarga é realizada por meio da definição de funções membro especiais ou funções friend que implementam o comportamento desejado para o operador. A sintaxe para sobrecarregar operadores varia dependendo do operador que se deseja sobrecarregar. A forma geral é a seguinte:

overloading.h

overloading.h

copy
1
return_type operator operator_symbol(parameters);

A sintaxe, ou mais especificamente, o número de parâmetros e o tipo de retorno, também depende se a sobrecarga de operadores está sendo feita como funções membro ou funções friend.

Member.h

Member.h

Friend.h

Friend.h

copy
123456
class Example { public: Example operator+ (const Example& other) { // Define behavior for operator+ } };

Tabela de operadores que podem ser sobrecarregados

Aqui está uma tabela listando todos os operadores que podem ser sobrecarregados. No entanto, é importante observar que, embora seja possível sobrecarregar esses operadores, não é de forma alguma necessário sobrecarregar todos eles para suas classes.

Sobrecarga dos operadores de inserção de fluxo

Para sobrecarregar os operadores << e >> para uma class, normalmente define-se uma função amiga ou uma função membro que recebe um fluxo de saída (std::ostream&) ou fluxo de entrada (std::istream&) como operando à esquerda e um objeto da sua class como operando à direita. Essa função então formata os dados do objeto e os envia para o fluxo ou os lê do fluxo.

Point.h

Point.h

copy
123456789101112131415
class Point { public: friend std::ostream& operator<<(std::ostream& out, const Point& point); friend std::istream& operator>>(std::istream& in, Point& point); private: int x, y; }; std::ostream& operator<<(std::ostream& out, const Point& point) { return out << "x: " << point.x << ", y: " << point.y << std::endl; } std::istream& operator>>(std::istream& in, Point& point) { return in >> point.x >> point.y; }

A sobrecarga dos operadores de inserção de fluxo, como o <<, permite definir um comportamento de saída personalizado para objetos das suas classes quando são enviados para um fluxo de saída como o std::cout. Esse recurso é especialmente útil para melhorar a legibilidade e usabilidade do seu código ao trabalhar com tipos de dados personalizados.

Note
Nota

A sobrecarga do operador << para fluxo de saída é mais comum do que a sobrecarga do operador >> para fluxo de entrada, pois operações de entrada com >> podem ser mais propensas a erros.

Sobrecarga de operadores aritméticos

É possível sobrecarregar outros operadores aritméticos (-, *, /, %) de maneira semelhante para realizar operações personalizadas com seus tipos definidos pelo usuário.

main.cpp

main.cpp

copy
12345678910111213141516171819202122
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} Point operator+(const Point& other) { return Point(x + other.x, y + other.y); } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p = Point(2, 4) + Point(2, 6); std::cout << p.getX() << ' ' << p.getY() << std::endl; }

O operador é sobrecarregado como uma função membro da Point class. Ele recebe outro objeto Point como parâmetro e retorna um novo objeto Point que representa a soma dos dois pontos. O operador + pode ser substituído por -, *, / ou %, com os devidos ajustes na lógica de implementação.

Incremento e Decremento

Tanto os operadores de incremento e decremento prefixados e postfixados (++ e --) podem ser sobrecarregados para classes personalizadas. Vamos começar com a versão prefixada:

main.cpp

main.cpp

copy
123456789101112131415161718192021222324
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} // Prefix increment operator (++point) Point& operator++() { ++x; ++y; return *this; } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p(2, 2); ++p; std::cout << p.getX() << ' ' << p.getY() << std::endl; }
Note
Nota

O operador de decremento é sobrecarregado de maneira semelhante ao operador de incremento, utilizando o operador -- e a operação de subtração.

Como pode ser visto, a sobrecarga dos operadores de incremento e decremento prefixados é direta. No entanto, torna-se mais complexo com as versões posfixadas. Lembre-se de que há uma diferença na ordem de execução entre as operações prefixadas e posfixadas.

Ao sobrecarregar os operadores de incremento e decremento posfixados, também é necessário implementar a característica de ordem de execução. Isso ficará semelhante ao seguinte:

main.cpp

main.cpp

copy
1234567891011121314151617181920212223242526
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} // Postfix increment operator (point++) Point operator++(int) { Point temp = *this; // Creating a temp variable ++(this->x); // Incrementing original Point's x ++(this->y); // Incrementing original Point's y return temp; // Returning created temp variable } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p(2, 2); p++; std::cout << p.getX() << ' ' << p.getY() << std::endl; }
Note
Nota

O parâmetro inteiro é passado sem nome apenas para sinalizar ao compilador que o operador de incremento pós-fixado está sendo sobrecarregado. Isso é necessário porque as declarações para os operadores prefixado e pós-fixado seriam, de outra forma, idênticas.

Na implementação do operador de incremento pós-fixado, o valor original do objeto é armazenado em uma variável temporária (temp). O objeto atual é então incrementado, mas o operador retorna o valor armazenado em temp. Isso significa que a variável é incrementada, mas a alteração só tem efeito na próxima expressão, pois o operador retorna o valor original.

question mark

O que significa sobrecarga de operadores?

Select the correct answer

Tudo estava claro?

Como podemos melhorá-lo?

Obrigado pelo seu feedback!

Seção 5. Capítulo 4

Pergunte à IA

expand

Pergunte à IA

ChatGPT

Pergunte o que quiser ou experimente uma das perguntas sugeridas para iniciar nosso bate-papo

course content

Conteúdo do Curso

C++ Poo

C++ Poo

1. Fundamentos de POO em C++
2. Construtores e Destrutores
3. Visão Geral do Encapsulamento
4. Visão Geral de Herança
5. Visão Geral do Polimorfismo

book
Sobrecarga de Operadores

Sobrecarga de operadores é um recurso poderoso em linguagens de programação orientadas a objetos que permite redefinir o comportamento dos operadores para classes definidas pelo usuário. Ao sobrecarregar operadores, é possível fornecer implementações personalizadas para operações envolvendo objetos da sua class, tornando o código mais intuitivo e expressivo.

Sintaxe da sobrecarga de operadores

A sobrecarga é realizada por meio da definição de funções membro especiais ou funções friend que implementam o comportamento desejado para o operador. A sintaxe para sobrecarregar operadores varia dependendo do operador que se deseja sobrecarregar. A forma geral é a seguinte:

overloading.h

overloading.h

copy
1
return_type operator operator_symbol(parameters);

A sintaxe, ou mais especificamente, o número de parâmetros e o tipo de retorno, também depende se a sobrecarga de operadores está sendo feita como funções membro ou funções friend.

Member.h

Member.h

Friend.h

Friend.h

copy
123456
class Example { public: Example operator+ (const Example& other) { // Define behavior for operator+ } };

Tabela de operadores que podem ser sobrecarregados

Aqui está uma tabela listando todos os operadores que podem ser sobrecarregados. No entanto, é importante observar que, embora seja possível sobrecarregar esses operadores, não é de forma alguma necessário sobrecarregar todos eles para suas classes.

Sobrecarga dos operadores de inserção de fluxo

Para sobrecarregar os operadores << e >> para uma class, normalmente define-se uma função amiga ou uma função membro que recebe um fluxo de saída (std::ostream&) ou fluxo de entrada (std::istream&) como operando à esquerda e um objeto da sua class como operando à direita. Essa função então formata os dados do objeto e os envia para o fluxo ou os lê do fluxo.

Point.h

Point.h

copy
123456789101112131415
class Point { public: friend std::ostream& operator<<(std::ostream& out, const Point& point); friend std::istream& operator>>(std::istream& in, Point& point); private: int x, y; }; std::ostream& operator<<(std::ostream& out, const Point& point) { return out << "x: " << point.x << ", y: " << point.y << std::endl; } std::istream& operator>>(std::istream& in, Point& point) { return in >> point.x >> point.y; }

A sobrecarga dos operadores de inserção de fluxo, como o <<, permite definir um comportamento de saída personalizado para objetos das suas classes quando são enviados para um fluxo de saída como o std::cout. Esse recurso é especialmente útil para melhorar a legibilidade e usabilidade do seu código ao trabalhar com tipos de dados personalizados.

Note
Nota

A sobrecarga do operador << para fluxo de saída é mais comum do que a sobrecarga do operador >> para fluxo de entrada, pois operações de entrada com >> podem ser mais propensas a erros.

Sobrecarga de operadores aritméticos

É possível sobrecarregar outros operadores aritméticos (-, *, /, %) de maneira semelhante para realizar operações personalizadas com seus tipos definidos pelo usuário.

main.cpp

main.cpp

copy
12345678910111213141516171819202122
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} Point operator+(const Point& other) { return Point(x + other.x, y + other.y); } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p = Point(2, 4) + Point(2, 6); std::cout << p.getX() << ' ' << p.getY() << std::endl; }

O operador é sobrecarregado como uma função membro da Point class. Ele recebe outro objeto Point como parâmetro e retorna um novo objeto Point que representa a soma dos dois pontos. O operador + pode ser substituído por -, *, / ou %, com os devidos ajustes na lógica de implementação.

Incremento e Decremento

Tanto os operadores de incremento e decremento prefixados e postfixados (++ e --) podem ser sobrecarregados para classes personalizadas. Vamos começar com a versão prefixada:

main.cpp

main.cpp

copy
123456789101112131415161718192021222324
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} // Prefix increment operator (++point) Point& operator++() { ++x; ++y; return *this; } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p(2, 2); ++p; std::cout << p.getX() << ' ' << p.getY() << std::endl; }
Note
Nota

O operador de decremento é sobrecarregado de maneira semelhante ao operador de incremento, utilizando o operador -- e a operação de subtração.

Como pode ser visto, a sobrecarga dos operadores de incremento e decremento prefixados é direta. No entanto, torna-se mais complexo com as versões posfixadas. Lembre-se de que há uma diferença na ordem de execução entre as operações prefixadas e posfixadas.

Ao sobrecarregar os operadores de incremento e decremento posfixados, também é necessário implementar a característica de ordem de execução. Isso ficará semelhante ao seguinte:

main.cpp

main.cpp

copy
1234567891011121314151617181920212223242526
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} // Postfix increment operator (point++) Point operator++(int) { Point temp = *this; // Creating a temp variable ++(this->x); // Incrementing original Point's x ++(this->y); // Incrementing original Point's y return temp; // Returning created temp variable } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p(2, 2); p++; std::cout << p.getX() << ' ' << p.getY() << std::endl; }
Note
Nota

O parâmetro inteiro é passado sem nome apenas para sinalizar ao compilador que o operador de incremento pós-fixado está sendo sobrecarregado. Isso é necessário porque as declarações para os operadores prefixado e pós-fixado seriam, de outra forma, idênticas.

Na implementação do operador de incremento pós-fixado, o valor original do objeto é armazenado em uma variável temporária (temp). O objeto atual é então incrementado, mas o operador retorna o valor armazenado em temp. Isso significa que a variável é incrementada, mas a alteração só tem efeito na próxima expressão, pois o operador retorna o valor original.

question mark

O que significa sobrecarga de operadores?

Select the correct answer

Tudo estava claro?

Como podemos melhorá-lo?

Obrigado pelo seu feedback!

Seção 5. Capítulo 4
some-alt