quarta-feira, 10 de junho de 2009




















Sobrecarga
de Operadores







Rafael
de Andrade Castro







Henrique
Augusto Diniz Ribeiro













O que é um
operador?







Um operador é
a parte de um código fonte que modifica um conteúdo de
uma variável, ou declara o seu valor inicial. Ex.
Multiplicação (*), Divisão(/), Adição(+),
Atribuição(=). Os operadores são nativos da
linguagem, ou seja, cada linguagem possui seus operadores definidos.
Os operadores possuem o conceito de serem unário ou binário,
ou seja, podem utilizar dois operandos ou apenas um.





Os operadores em uma
linguagem de programação são apenas símbolos
que por trás existem funções que determinam o
que aquele símbolo faz com o valor, as funções
de operadores são pré-definidas apenas para os tipos
primitivos de variáveis, no qual essas funções
não têm como serem alteradas, pelo fato de que elas já
são nativas da linguagem, isso faz com que mesmo utilizando a
sobrecarga destes operadores não tem como fugir de sua
funcionalidade natural.







A sobrecarga de
operadores é feito a partir de objetos de uma classe, que são
dados abstratos, sendo assim para sobrecarregar operadores é
obrigatório que a linguagem tenha recursos de orientação
a objeto.







Observações:













  • Não se pode criar novos
    operadores, apenas sobrecarregar operadores já existentes.









  • Não se pode alterar a
    propriedade do operador, ou seja, se ele é binário sua
    sobrecarga deverá permanecer binária, se ele for
    unário sua sobrecarga deverá permanecer unária.






Operadores que podem ser sobrecarregados:



Operadores que não
podem ser sobrecarregados:



Exemplo
de sobrecarga de operadores unários:







class
ponto







{







private:







intx,y;







public:







ponto(int
x1=0, int y1=0)







{







x=x1;







y=y1;








}//constructor







Ponto
operator++() //função operadores 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







}







Observe.:
p1++; é equivalente a p1.operator++();















Exemplo
de sobrecarga de operadores binários:







class
venda







{







venda
operador+(venda v) const; //função operadora







}







venda
venda :: operator + (venda v) const //soma dois objetos







{







int
pec = npecas + v.pecas;







float
pre = preco + v.pecas;







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
operador + (ponto p) const //soma dois objetos







{







return
ponto(x+p.x,y+p.y);







}







ponto
operador + (int n) const //soma um número a um objeto







{







return
ponto(x+n,y+n);













}















void
main()







{







p3=p1+p2;







p4=p1+5;







}















Observe.:
p4=p1+5;







É
equivalente a p4=p1.operator+(5); por isso não podemos
escrever instruções p4=5+p1; que seriam interpretadas
como: p4=5.operator+(p1)//errado















Expressões
Lógicas


















Quando
uma expressão lógica é calculada dentro do
programa, é feita a seguinte associação numérica
com o valor da expressão:







verdadeiro
– 1







falso
– 0







Mais
genericamente o valor zero está associado ao valor lógico
falso, enquanto que qualquer valor diferente de zero está
associado ao valor lógico verdadeiro.







Assim,
uma comparação como por exemplo a > b, quando
calculada, tem associado a si o valor 1 se a > b (verdadeira) e 0
se a <= b (falsa).







Da
mesma forma uma expressão aritmética como por exemplo a
+ b, pode ser considerada falsa ou verdadeira, conforme seu valor
seja zero ou diferente de zero.







O
programa abaixo mostra algumas variações e exemplos da
utilização de expressões aritméticas como
lógicas e vice-versa. Verifique o que será impresso
abaixo:







#include
<stdio.h>







int
main()







{char
a;







int
b;







int
x = 0, y = 1;







//
os valores atribuidos a “a” e “b” são
zero e um, dependendo se a







//
expressão é verdadeira ou falsa







a
= x < y;







cout<<"\n
(1) valor de a = "<<a;







a
= x < y && y > 0;







cout<<"\n
(2) valor de a = "<<a;







a
= x > y;







cout<<"\n
(3) valor de a = “<<a;







b
= x+y < x*y x == y;







cout<<"\n
(4) valor de a = "<<b;
















//
comparações







if
(1) cout<<\n (5) sempre verdadeiro";







if
(-5) cout<<\n (6) sempre verdadeiro";







if
(0) ;







else
cout<<"\n (7) sempre falso";







if
(1 == 1) cout<<"\n (8) sempre verdadeiro";







if
(0 == 0) cout<<"\n (9) sempre verdadeiro";
















//
a também pode receber valores aritméticos entre 0 e 255







a
= x * y;







if
(a) cout<<”\n (10) verdadeiro quando a diferente de zero
- a = ”<<a;







else
cout<<"\n (10) falso quando a igual a zero - a = ”<<a;
















//
a e b como valores lógicos







a
= x * y;







b
= x + y;







if
(a && b)







cout<<"\n
(11) verdadeiro se a e b não zero: a = “<<a<<”b
= "<<b;







else
cout<<"\n (11) falso se a ou b são zero: a =
“<<a<<”b = “<<b;
















b
= 0;







while
(1) // a repetição será infinita







{if
(b++ > 4) break; // força a saída







cout<<"\n
(“<<11+b<<”) valor de b = “<<b;







}







//
outro exemplo de while







a
= 1;







b
= 0;







while
(a)







{cout<<"\n
(“<<18+b<<”) valor de a = “<<a<<”
valor de b = ”<<b;







a
= (b++) < 3;







}







cout<<"\n
(“<<18+b<<”) valor final de a = “<<a<<”
e de b = “<<b;







}







(1)
valor de a = 1







(2)
valor de a = 1







(3)
valor de a = 0







(4)
valor de a = 0







(5)
sempre verdadeiro







(6)
sempre verdadeiro







(7)
sempre falso







(8)
sempre verdadeiro







(9)
sempre verdadeiro







(10)
falso quando a igual a zero - a = 0







(11)
falso se a ou b são zero: a = 0 b = 1







(12)
valor de b = 1







(13)
valor de b = 2







(14)
valor de b = 3







(15)
valor de b = 4







(16)
valor de b = 5







(18)
valor de a = 1 valor de b = 0







(19)
valor de a = 1 valor de b = 1







(20)
valor de a = 1 valor de b = 2







(21)
valor de a = 1 valor de b = 3







(22)
valor final de a = 0 e de b = 4
















Assim
supondo int x,y; as seguinte expressões lógicas são
equivalentes:







(x
&& y) (x != 0 && y != 0) !(x == 0 y == 0)







(x
y) (x != 0 y!= 0) !(x == 0 && y == 0)







Lembram-se
daquele problema que dada uma sequência terminada por zero,
calcular a soma dos elementos da sequência?







int
soma, x;







:







:







x
= 1; soma = 0;







while
(x)







{







cin>>x;







soma
= soma + x;







}







cout<<“o
valor da soma = “<<soma;







Otimização
do Cálculo de Expressões Lógicas

















Quando
se usa uma expressão composta, com os operadores && e
(and e or), o compilador otimiza o cálculo das mesmas,
muitas vezes não as calculando até o fim, quando o seu
valor já está determinado no meio do cálculo.







Por
exemplo, considere a expressão (a > b && c > d).
Se a > b já é falso, não é necessário
verificar se c > d, pois o resultado da expressão já
será falso. O mesmo ocorre com (a > b c > d). Se a >
b é verdadeiro, a expressão é verdadeira
independente se c > d ou não.







Normalmente
os compiladores da linguagem c usam esta regra como padrão,
sendo possível alterá-la através de uma opção
de compilação para que o cálculo seja completo.







Em
alguns casos, o resultado pode ser diferente, pois o cálculo
da expressão completa tem efeitos colaterais. De uma maneira
geral o uso de expressões que pressupõe a otimização
deve ser feito com muito cuidado, para evitar tais efeitos
colaterais.







Considere
por exemplo a seguinte solução para verificar se x é
igual a algum elemento de um vetor a de n elementos.







i
= 0;







while
(i < n && a[i] != x) i++;







Considerando
o caso em que x não é igual a nenhum dos elementos, se
o cálculo da expressão for otimizada, o programa sai do
while quando i = n e não realiza a comparação
a[i] != x, pois se realizasse estaria errado, pois o elemento a[n]
está fora dos n elementos considerados.







Invertendo
agora a expressão acima:







i
= 0;







while
(a[i] != x && i < n) i++;







Embora
a operação && seja comutativa, a solução
está errada, pois quando i = n a comparação a[n]
!= x será efetuada, pois vem antes que a comparação
i < n.
















Referencias















http://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Sobrecarga_de_operadores















Deitel,Harvey
M. C++ Como Programar. Tradução Carlos Arthur
Lang Lisbôa e Maria Lúcia Blank Lisboa. Porto Alegre.
Reimpressão Bookman,2001

































Nenhum comentário:

Postar um comentário