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
Identificadores • Nomes dados às variáveis, classe ou método. • Pode iniciar com um caractere Unicode, sublinhado, ou sinal de dólar ($)
Leia maisSobrecarga de operadores_Ednaldo_POO
fração (x/y) e os operadores relacionados a ela. Eles permitem que o código
Leia mais