O documento discute a sobrecarga de operadores em C++. Ele explica que sobrecarregar um operador permite aplicá-lo a tipos de dados definidos pelo usuário como classes e estruturas. Em seguida, apresenta exemplos de sobrecarga de operadores unários, binários e de acesso a elementos de vetores e matrizes.
1. C++ - Sobrecarga de Operadores
Sobrecarregar um operador significa redefinir seu símbolo, de maneira que ele
se aplique também a tipos de dados definidos pelo usuário como classes e estruturas.
A implementação de sobrecarga de operadores é definida por meio de funções
chamadas operadoras , criadas como membro da classe ou como funções globais.
Limitações : Respeitar a definição original do operador
• Não é possível mudar o operador de unário para binário.
• Não se pode inventar símbolos novos.
• Não é possível modificar a precedência de operadores por meio de
sobrecarga.
• Operadores que não podem ser sobrecarregados:
• . (operador ponto)
• :: (operador de resolução de escopo)
• ? : (operador ternário)
Sobrecarga de Operadores Unários : Operador de incremento pré-fixado
class ponto
{ private :
int x, y;
public :
ponto (int x1=0, int y1=0) {x=x1; y=y1;} // construtor
ponto operator ++( ) // função operadora pré-fixada
{ ++x; ++y;
return ponto(x, y);
}
void printpt( ) const // imprime ponto
{ cout << ‘(‘ << x << ‘,’ << y << ‘)’; }
};
void main( )
{ ponto p1, p2(2,3), p3; // declara e inicializa
cout << “n p1 = “ ; p1.printpt( ); // imprime
cout << “n++p1 = “ ; (++p1).printpt( ); // incrementa e imprime
p3 = ++p2; // incrementa e atribui
cout << “n p3 = “ ; p3.printpt( ); // imprime }
2. Observ.: ++p1 ; é equivalente a p1.operator++( );
Sobrecarga do operador de incremento pós-fixado : Para distinguir entre as
formas pré e pós-fixada, o compilador utiliza o número de argumentos da função
operadora.
• sem parâmetro : pré-fixado operator ++ ( )
• com um parâmetro do tipo int : pós-fixadooperator ++ (int)
ponto operator ++(int) // função operadora pós-fixada
{ ++x; ++y;
return ponto(x-1, y-1);
}
Sobrecarga de operadores binários : função operadora com um argumento.
Ex.: sobrecarga do + aritmético
class venda
{ ...
venda operator + (venda v) const; // função operadora
...
}
venda venda :: operator + (venda v) const // soma dois objetos
{ int pec = npecas + v.pecas;
float pre = preco + v.preco;
return venda(pec, pre);
}
...
void main( )
{ venda A(58, 12734.53), B(30, 6000.30), T;
T = A + B; ... }
Somando objetos da classe ponto : funções operadoras
class ponto
{ ...
ponto operator + (ponto p) const // soma dois objetos
{ return ponto(x+p.x, y+p.y); }
ponto operator + (int n) const // soma um número a um objeto
{ return ponto(x+n, y+n); }
}
void main( )
{ ...
4. }
cout << “ nLista Original”;
for (int i=0; i<n ; i++)
{ cout << “ ns[ “ << i << “] = “;
s[i].print( );
}
ordena (s, n);
cout << “ nLista Ordenada”;
for (int i=0; i<n ; i++)
{ cout << “ ns[ “ << i << “] = “;
s[i].print( );
}
}
void ordena (string s[ ], int n)
{ string temp; int j;
for (int i=0; i<n ; i++)
for ( j=i+1; j<n ; j++)
if (s[i] > s[j])
{ temp =s[i]; s[i] = s[j]; s[j] = temp }
}
Sobrecarga do operador [ ] : checagem de limites de matrizes
#include <iostream.h>
#include <iomanip.h>
const MAX = 50;
class matriz
{ private :
float n[MAX];
public :
matriz( ); // construtor
float& operator [ ] (int indice); // sobrecarga de [ ]
float media( int i);
};
matriz :: matriz( )
{ for( int i=0; i < MAX; i++) n[i] = 0.0; }
float& matriz :: operator [ ] (int indice)
5. { static float x = -1;
if ( indice >= 0 && indice < MAX)
return n[indice];
else
{ cout << "nFora de limite";
return x; }
}
float matriz :: media (int i)
{ float m= 0.0;
for (int j=0; j<i; j++) m += n[j];
return m/float(i); }
void main( )
{ matriz notas;
cout << setprecision(2);
int i=0;
do {
cout << ""nDigite a nota do aluno " << (i+1) << " : ";
cin >> notas [i];
} while (notas[i++] >= 0);
cout << "nMedia das notas : " << notas.media(i); }
Observ. : A função operator[ ] retorna uma referência a um elemento da matriz n.
Dessa forma, a expressão notas[i] age como o próprio elemento da matriz privada,
podendo ser usada em instruções como
cin >> notas[i]; ou notas[i] = 6.7;
A função operator[ ] cria uma variável static , pois não é possível retornar
referência a uma variável automática.
Conversões entre tipos básicos :
• implícita double dvar = 'A';
• explícita (operdor molde) double dvar = double ('A');
Conversão de tipos com classes :
• objetos a tipos básicos - sobrecarga do operador molde criando função
conversora.
Ex.: Conversão de um objeto string a tipo int ou float
#include <stdlib.h>
6. ...
class string
{ ...
operator int( ) const // função conversora
{ return atoi(str); }
operator double( ) const // função conversora
{ return atof(str); }
...
};
void main ( )
{ string s1("1234"), s2("1234.56");
int i = s1; // conversão de string para int
double d = s2; // conversão de string para double
...
}
• tipos básicos a objetos : sobrecarga do operador de atribuição =
Ex.: conversão de um int a um objeto string.
Class string
{ ...
void operator = (int n) // sobrecarga do operador de atribuição
{ itoa(n, str, 10); }
...
};
void main ( )
{ string s;
s = 5392; // conversão de inteiro para string
...
}
• objeto a objeto (classes diferentes ) - objA = objB
Dois métodos :
• função-membro conversora da classe B
• construtor membro da classe A
Primeiro método : função conversora
Classes graus e radianos. Converter objetos da classe radianos em objetos da classe
graus (grau = radiano). Função conversora na classe radianos.
7. #include <iostream.h>
#include <iomanip.h>
#define PI 3.141592653
class graus
{ private :
double g;
public :
graus (double x) { g=x; }
graus ( ) { g = 0; }
void print( )
{ cout << setiosflags (ios :: fixed)
<< setiosflags (ios :: showpoint)
<< setprecision (2) << g << “ xf8n”;
}
};
class radianos
{ private:
double rad;
public :
radianos (double r) { rad = r ; }
radianos ( ) {rad = 0.0 ; }
operator graus ( ) // função conversora de rad. para graus
{ return graus(180.0*rad/PI); }
void print( )
{ cout << setioflags (ios :: fixed)
<< setiosflags (ios :: showpoint)
<< setprecision (2) << rad << “ rad n”;
}
};
void main( )
{ graus gr;
radianos rd(PI);
gr = rd; // converte radianos para graus
...
}
Segundo método : função construtora (implementada na classe graus)
8. class radianos
{ ...
public :
double getrad ( ) {return rad; }
...
};
class graus
{ ...
graus (radianos rd) // construtor para conversão
{ g = (180.0 * rd.getrad( ) / PI; }
...
};
void main( )
{ graus gr;
radianos rd(PI);
gr = rd; // converte radianos para graus
...
}
• conversões dos dois lados : (graus em radianos e radianos em graus)
As duas funções presentes na mesma classe.
class radianos
{
...
};
class graus
{
...
public :
graus (radianos rd) // construtor para conversão
{ g = (180.0 * rd.getrad( ) / PI; }
operator radianos ( ) // função conversora de tipo
{ return radianos(g * PI / 180.0); }
...
};
9. void main ( )
{ graus gr, gr1(180.0);
radianos rd(PI), rd1;
gr = rd; // converte radianos para graus
rd1 = gr1; // converte graus para radianos
...
}
Conversões : quando usar o quê ? Quando as duas classes são acessíveis,
podemos escolher entre o uso de função conversora ou construtora. Porém se uma
das classes pertencer a uma biblioteca, da qual não temos acesso ao fonte, dois casos
podem acontecer . Se usarmos instruções como:
• meu_obj = lib_obj;
devemos implementar função construtora de um argumento. Já nas instruções:
• lib_obj = meu_obj;
temos que implementar função conversora de tipo.
Exercícios
Assunto : Sobrecarga de Operadores.
Crie uma classe que defina um número complexo x + yi, onde x e y são do
tipo float e i é a raiz quadrada de -1. Defina as operações aritméticas entre números
complexos nesta classe.
Prática VIII
Defina uma classe chamada fração. Esta classe deve armazenar o numerador e o
denominador de uma fração em duas variáveis inteiras. Inclua :
a ) dois construtores: o primeiro sem argumentos e o outro que recebe
numerador e denominador da fração;
b) uma função-membro que retorna o numerador e outra que retorna o
denominador;
c) as operações de adição, subtração, multiplicação e divisão;
d ) as operações de incremento e decremento pré-fixadas;
e) um conversor de tipo que converte um objeto fração para um tipo float;