C++ - Sobrecarga de Operadores Sobrecarregar um operador

Transcrição

C++ - Sobrecarga de Operadores Sobrecarregar um operador
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;
cout << “\n p1 = “ ; p1.printpt( );
cout << “\n++p1 = “ ; (++p1).printpt( );
p3 = ++p2;
cout << “\n p3 = “ ; p3.printpt( );
// declara e inicializa
// imprime
// incrementa e imprime
// incrementa e atribui
// imprime
}
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.
operator ++ ( )
• sem parâmetro : pré-fixado
• com um parâmetro do tipo int : pós-fixadooperator ++ (int)
ponto operator ++(int)
{
++x; ++y;
return ponto(x-1, y-1);
}
// função operadora pós-fixada
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
{
return ponto(x+p.x, y+p.y);
ponto operator + (int n) const
{
return ponto(x+n, y+n);
}
void main( )
{
...
// soma dois objetos
}
// soma um número a um objeto
}
p3 = p1 + p2;
p4 = p1 + 5;
...
}
p4 = p1.operator + (5);
Observ.: p4 = p1 + 5 ; é equivalente a
por isso não podemos escrever instruções p4 = 5 + p1;
que seriam interpretadas como: p4 = 5. operator + (p1) // errado
Operadores para manipular strings : +=, +, <, ==, >
enum Boolean { False, True};
class string
{
...
string operator +=(string s) const
{
string temp;
if (strlen(str) + strlen(s.str) < MAX)
{
strcpy( temp.str, str);
strcat(temp.str, s.str);
}
else cout << “ \nMemória Esgotada!! “;
return temp;
}
string operator +(string s) const
// concatena
{
string temp;
temp +=s.str;
return temp;
}
Boolean operator < (string s) const
{
return (strcmp(str, s.str) < 0) ? True : False; }
Boolean operator ==(string s) const
{
return (strcmp(str, s.str) == 0) ? True : False;}
string getstr( )
{
gets(str);
return string(str);
...
}
void main ( )
{
string s[MAX];
for (int n=0; n<= 80; n++)
{
cout << “ \nDigite nome ou <enter> para encerrar “;
if (s[n].getstr( ) == “”) break;
}
}
}
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)
}
}
{
}
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++)
return m/float(i);
}
m += n[j];
}
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
• explícita (operdor molde)
Conversão de tipos com classes :
double dvar = 'A';
double dvar = double ('A');
• 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>
...
class string
{
...
operator int( ) const
{
return atoi(str);
// função conversora
}
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.
#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 << “ \xf8\n”;
}
};
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)
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); }
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;

Documentos relacionados

Módulo 03 Identificadores, Palavras Reservadas, e - BCC Unifal-MG

Módulo 03 Identificadores, Palavras Reservadas, e - BCC Unifal-MG Identificadores • Nomes dados às variáveis, classe ou método. • Pode iniciar com um caractere Unicode, sublinhado, ou sinal de dólar ($)

Leia mais

Sobrecarga de operadores_Ednaldo_POO

Sobrecarga de operadores_Ednaldo_POO fração (x/y) e os operadores relacionados a ela. Eles permitem que o código

Leia mais