Ir para conteúdo
Fórum Script Brasil
  • 0

Sobrecarga De Operador


Andersonjb

Pergunta

Hoje eu estava estudando um pouquinho sobre sobrecarga de operadores. Bem, e surgiu a duvida: porque mudar a forma de um operador trabalhar se a sua forma de trabalho e muito boa, ou quase que perfeita? Qual e a verdadeira logica de uma sobrecarga? alguém poderia me explicar?

Link para o comentário
Compartilhar em outros sites

21 respostass a esta questão

Posts Recomendados

  • 0
Hoje eu estava estudando um pouquinho sobre sobrecarga de operadores. Bem, e surgiu a duvida: porque mudar a forma de um operador trabalhar se a sua forma de trabalho e muito boa, ou quase que perfeita? Qual e a verdadeira logica de uma sobrecarga? alguém poderia me explicar?

A idéia é personalizar a forma como os operadores funcionarão com *seus* objetos. Você pode querer que ao "somar" dois objetos seus, seja retornado um terceiro que represente essa "soma". Ou criar personalizações na escrita do código, como "cin" e "cout" que utilizam as sobrecargas de "<<" e ">>", respectivamente. Utilizar um sinal de "+" para concatenar duas strings não é muito mais claro do que ter que utilizar uma função para isso? Como você já deve saber, não existe um tipo "string" em C, mas sim apenas vetores de char que são o mais próximo desse tipo. Em C++ adicionou-se uma classe string que simula as "strings" que vemos em outras linguagens. Agora, veja a discrepância entre as versões de código (de C para C++):

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>

using namespace std;

int main() {
    // O jeito C++
    string s1 = "teste";
    string s2 = " e outro teste";
    cout << s1 << endl;
    cout << s2 << endl;
    cout << s1+s2 << endl;

    // O jeito C
    char *cs1 = "teste";
    char *cs2 = " e outro teste";
    char cs3[20];
    cs3[0] = '\0';
    
    printf("%s\n", cs1);
    printf("%s\n", cs2);
    strcat(cs3, cs1);
    strcat(cs3, cs2);
    printf("%s\n", cs3);
    
    system("pause");
}

O que aquele "s1+s2" fazem resulta no mesmo que aquelas duas linhas de "strcat". A diferença é que uma "string" *não* é um vetor de char, mas sim um objeto como qualquer outro. Qual o resultado da soma de dois objetos quaisquer? É isso que a sobrecarga nos permite decidir. C/C++ não possuem um tipo nativo para lidar com números complexos, mas poder-se-ia criar uma classe para tal (é bem provável que já tenham feito) e a "soma" entre dois números complexos seria perfeitamente válida ao se utilizar a sobrecarga.

Sacou a idéia? wink.gif

Abraços,

Graymalkin

Link para o comentário
Compartilhar em outros sites

  • 0

Beleza, gray, eu consegui entender a logica, mas posso te pedir um favor? Tem como você postar algum exemplo de uma sobrecarga simples aqui no post? Eu so tenho codigos meio complicados aqui e não entendo bulhufas!:S Se der, valeu, hein!

Link para o comentário
Compartilhar em outros sites

  • 0
Beleza, gray, eu consegui entender a logica, mas posso te pedir um favor? Tem como você postar algum exemplo de uma sobrecarga simples aqui no post? Eu so tenho codigos meio complicados aqui e não entendo bulhufas!:S Se der, valeu, hein!

Sim, aí vai um exemplo que sobrecarrega o operador << para que você possa personalizar como o seu objeto vai aparecer quando utiliza-se o cout.

#include <iostream>
#include <conio.h>
#include <stdlib.h>

using namespace std;

class Cliente {
    friend ostream& operator<<(ostream& saida, Cliente *obj);
        
    private:
        char *nome;
        int idade;
                
    public:
        Cliente(char *nome, int idade);
};

Cliente::Cliente(char *nome, int idade) {
    this->nome = nome;
    this->idade = idade;
};

ostream& operator<<(ostream& saida, Cliente *obj) {
    saida << obj->nome << " - " << obj->idade;
    return saida;
}

int main() {
    Cliente *c1 = new Cliente("Junior", 21);
    cout << c1 << endl;
    system("pause");
}

Note que se não existir essa sobrecarga, o resultado mostrado ali em cout << c1 << endl; é o endereço do ponteiro c1. Como isso não nos interessa (nesse caso, é claro), fazemos então com que o mostrado seja o nome do cliente seguido por um espaço-hífen-espaço e sua respectiva idade.

Certo? wink.gif

Abraços,

Graymalkin

Link para o comentário
Compartilhar em outros sites

  • 0

E ai, gray, firme? Bem, eu não entendi nada disto aqui:

ostream& operator<<(ostream& saida, Cliente *obj) {
   saida << obj->nome << " - " << obj->idade;
   return saida;
E isso aqui tb não:
friend ostream& operator<<(ostream& saida, Cliente *obj);
E isso aqui, rsrs, sou burro, ne?
this->nome

Bem, se der pra responder valewus, e que sobrecarga e uma coisa que não entra na minha cabeça!

Link para o comentário
Compartilhar em outros sites

  • 0

E ai, gray, firme?

Beleza, e tu? smile.gif

Bem, eu não entendi nada disto aqui:

ostream& operator<<(ostream& saida, Cliente *obj) {
  saida << obj->nome << " - " << obj->idade;
  return saida;
Ao estudar sobre a sobrecarga de operadores você deve ter visto que ela não passa de uma função normal, porém seu nome é na forma "operator<op>" onde "<op>" é substituído pelo operador a ser sobrecarregado. Além disso, os parâmetros a serem recebidos por cada um dos operadores podem ser diferentes. Nesse caso aí, o operador << receberá um ostream (um objeto que escreve no console) e o objeto a ser escrito (que é o ponteiro obj). Esse objeto "saida" é igual ao "cout", por isso jogamos o que queremos escrever nele do mesmo jeito que faríamos com "cout". Em seguida o retornamos para que seja possível realizar essa mesma operação com múltiplos <<.
E isso aqui tb não:
friend ostream& operator<<(ostream& saida, Cliente *obj);
Isso é apenas a declaração da sobrecarga do operador << dentro da classe. Creio que você já tenha lido sobre a visibilidade "friend" de uma função, não? Uma função friend (amiga) é definida fora de uma classe, porém tem acesso aos atributos privados da classe. Note que "nome" e "idade" são privados e não deveriam ser acessíveis por "->" ou ".", porém na definição da função eles são acessados sem problemas:
saida << obj->nome << " - " << obj->idade;
Isso porque a função de sobrecarga de << é "amiga" da classe (a condição de "amiga" [friend] permite que ela compartilhe de todos os seus segredos [atributos privados]... hehehehe...biggrin.gif... afinal de contas, um amigo não guarda segredos, não é o que dizem? smile.gif). Sacou? wink.gif
E isso aqui, rsrs, sou burro, ne?
this->nome
Burrice é quando se sabe algo e não se faz o devido uso da coisa. Ou seja, aquele que *desconhece* algo não é burro, é apenas "ignorante" (veja que "ignorante" aqui é "aquele que ignora [desconhece] algo" e não uma pessoa bruta ou bronca, como se utiliza no "popular"). Quanto ao código, o "this" você deve saber que ele é um ponteiro para o próprio objeto. Se ele é um ponteiro, para acessarmos seus atributos, temos que utilizar a seta (->) ou desreferenciá-lo:
(*this).nome = nome;

Como acho que isso não é muito legível, prefiro utilizar a seta. Komprenas? wink.gif

Bem, se der pra responder valewus, e que sobrecarga e uma coisa que não entra na minha cabeça!

A teoria da sobrecarga não é muito difícil de ser assimilada. Quando somamos dois números inteiros, 2+3, por exemplo, teremos o total de 5 (também inteiro). Agora, imaginemos que 2 é um objeto e 3 é outro objeto. Qual o resultado da soma entre o objeto 2 e o objeto 3? Resposta: o objeto 5. A resposta é a mesma quando estamos lidando com 2 sendo um inteiro ou sendo um objeto, certo? Certo porque internamente a soma entre os objetos, em algum ponto, irá encontrar seu valor inteiro, realizar a soma e devolver um objeto com o novo valor. Ou seja, é fácil quando se pode quantificar a coisa. Porém, quando se lida com objetos, deve-se ter em mente que eles podem não ter um único valor. Se eu tivesse dois objetos, um da classe Homem e outro da classe Mulher, e resolvesse somá-los, o que eu deveria obter? Um objeto da classe CasalFelizParaSempre? Um objeto da classe Bebê? Outro objeto das classes Homem ou Mulher? É exatamente isso que a sobrecarga de um operador + nos permite decidir. Estaremos explicitamente dizendo o que deve ser retornado quando uma determinada operação entre um objeto e outro for realizada. Got it? wink.gif

Abraços,

Graymalkin

Link para o comentário
Compartilhar em outros sites

  • 0

Ei, gray, me explica uma coisa: qual a diferença entre se declarar a sobrecarga fora da classe e dentro dela? Bem, eu vi no meu livro e li, e não consegui entender. Tanto que la, quando você declara uma sobrecarga dentro da classe, você so chama um parametro, por exemplo:

class Money
{
public:
    Money( );
    Money(double amount);
    Money(int dollars, int cents);
    Money(int dollars);
    double getAmount( ) const;
    int getDollars( ) const;
    int getCents( ) const;
    void input( ); //Reads the dollar sign as well as the amount number.
    void output( ) const;
    [COLOR=red]const Money operator +(const Money& amount2) const;[/COLOR]
    const Money operator -(const Money& amount2) const;
    bool operator ==(const Money& amount2) const;
    const Money operator -( ) const;
private:
    int dollars; 
    int cents; 

    int dollarsPart(double amount) const;
    int centsPart(double amount) const;
    int round(double number) const;
};

Observe a declaração da sobrecarga em vermelho, ele so pede um parametro, e obeserve tb que o operador não e unario. você pode me ajudar com isto?

Link para o comentário
Compartilhar em outros sites

  • 0
Ei, gray, me explica uma coisa: qual a diferença entre se declarar a sobrecarga fora da classe e dentro dela? Bem, eu vi no meu livro e li, e não consegui entender. Tanto que la, quando você declara uma sobrecarga dentro da classe, você so chama um parametro, por exemplo:

class Money
{
public:
    Money( );
    Money(double amount);
    Money(int dollars, int cents);
    Money(int dollars);
    double getAmount( ) const;
    int getDollars( ) const;
    int getCents( ) const;
    void input( ); //Reads the dollar sign as well as the amount number.
    void output( ) const;
    [COLOR=red]const Money operator +(const Money& amount2) const;[/COLOR]
    const Money operator -(const Money& amount2) const;
    bool operator ==(const Money& amount2) const;
    const Money operator -( ) const;
private:
    int dollars; 
    int cents; 

    int dollarsPart(double amount) const;
    int centsPart(double amount) const;
    int round(double number) const;
};

Observe a declaração da sobrecarga em vermelho, ele so pede um parametro, e obeserve tb que o operador não e unario. você pode me ajudar com isto?

Você não precisa de outro parâmetro porque a operação vai ser realizada entre o *seu* objeto e o objeto passado. Ou seja, você já tem o seu objeto apontado pelo ponteiro this. Portanto, o parâmetro que não aparece ali pode ser substituído justamente pelo próprio objeto (this).

Sacou? wink.gif

Abraços,

Graymalkin

Link para o comentário
Compartilhar em outros sites

  • 0

E se minha classe tiver 2 objetos?

O this aponta para o próprio objeto. Se você criou obj1 e obj2 da classe Classe, então o this de obj1 vai apontar para obj1 e o this de obj2 vai apontar para obj2. A classe é só como se fosse um modelo e o objetos são *cópias isoladas* (de um modelo, que no caso é a classe). Entendeu? wink.gif

Abraços,

Graymalkin

Link para o comentário
Compartilhar em outros sites

  • 0
Ta, no caso, o this aponta pra um membro independente da classe, correto? Mas nesse codigo não tem o this. E acabei não intendendo nada, rsrs

Não... o this aponta para o próprio objeto dentro dele mesmo. Necessariamente você não precisa utilizar o this mas é importante ter em mente isso. Se você sobrecarrega o operador + para uma determinada classe, o que será a soma de...

obj1+obj2;
... no caso? Imagine que a linha acima você convertida para a chamada de um método:
obj1.operator+(obj2);

Ao chegar no método operator+ você já terá todos os membro de obj1 (afinal de contas, este é um método *do* objeto) e seu parâmetro é somente à quem ele deverá ser "somado". Sacou? wink.gif

Acho que o problema aqui está sendo a distinção entre classe e objeto. O que você entende por estas duas coisas? Qual a diferença entre elas?

Abraços,

Graymalkin

Link para o comentário
Compartilhar em outros sites

  • 0

não, eu sei disso, sei que quando eu somo dois objetos eu tb estou somando as variaveis membros da classe respectiva a classe, pois o objeto e uma instancia da classe. O que eu não consigo entender de fato e o porque quando e declarada uma sobrecarga dentro da classe, so se usa um parametro, entendeu?

Link para o comentário
Compartilhar em outros sites

  • 0
não, eu sei disso, sei que quando eu somo dois objetos eu tb estou somando as variaveis membros da classe respectiva a classe, pois o objeto e uma instancia da classe. O que eu não consigo entender de fato e o porque quando e declarada uma sobrecarga dentro da classe, so se usa um parametro, entendeu?

Simplesmente porque não precisa de outro (o *outro* é o próprio objeto). Um objeto conhece a si mesmo e todos os seus membros, então para que passá-lo novamente (como um parâmetro) para ele mesmo? Ou seja, a idéia de apenas um parâmetro é que você só precisa informar qual o objeto que deverá ser somado a quem está chamado a soma. Entendeu? wink.gif Imagine que 2, e na soma 2+3, o 2 chama o método operator+ e só passa o 3 como argumento. Ou seja, o 2, que é quem está chamado o método operator+, sabe quem ele mesmo é, então ele não precisa ser passado explicitamente (está implícito). Sacou?

Abraços,

Graymalkin

Link para o comentário
Compartilhar em outros sites

  • 0

Tudo be, entendi, mas o caso, mesmo chamando so um parametro, a soma dos dois deve ser definida dentro do codigo da sobrecarga, certo? E uma perguntinha: quando eu sobrecarrego um operador dentro de uma classe, essa sobrecarga so funciona com objetos desta classe ou com qualquer operação?

Link para o comentário
Compartilhar em outros sites

  • 0

Tudo be, entendi, mas o caso, mesmo chamando so um parametro, a soma dos dois deve ser definida dentro do codigo da sobrecarga, certo?

Exato. smile.gif

E uma perguntinha: quando eu sobrecarrego um operador dentro de uma classe, essa sobrecarga so funciona com objetos desta classe ou com qualquer operação?

Depende do tipo do parâmetro. Você não é obrigado a fazer com que somente objetos da sua classe possam sofrer uma determinada operação. Ou seja, é possível criar uma sobrecarga onde seu objeto vai ser somado a um inteiro ou a um char, por exemplo.

Abraços,

Graymalkin

Link para o comentário
Compartilhar em outros sites

  • 0

Ei gray, eu entendi a logica de se usar somente um parametro, mas eu não consigo estabelecer uma çogica ou um algoritmo pra formular isso no programa, como com somente um parametro eu posso somar dois objetos, como ficaria meu codigo, se pode me dar uma mao?

Link para o comentário
Compartilhar em outros sites

  • 0
Ei gray, eu entendi a logica de se usar somente um parametro, mas eu não consigo estabelecer uma çogica ou um algoritmo pra formular isso no programa, como com somente um parametro eu posso somar dois objetos, como ficaria meu codigo, se pode me dar uma mao?

Acho que com um exemplo vai ficar mais simples, então fiz este aqui:

#include <stdlib.h>
#include <iostream>
#include <string.h>

using namespace std;

class Texto {
      private:
             char *texto;
      public:
             Texto(char *s);
             char *gettexto();
             Texto operator+(Texto t);
};

Texto::Texto(char *s) {
    this->texto = s;
}

char *Texto::gettexto() {
    return this->texto;
}

Texto Texto::operator+(Texto t) {
    char *texto1 = this->gettexto(); // Texto *deste* (this) objeto
    char *texto2 = t.gettexto(); // Texto do objeto passado 
    // Percebe agora os dois elementos a serem "somados"?
    
    int tam1 = strlen(texto1);
    int tam2 = strlen(texto2);
    int tamanho_total = tam1+tam2+1;

    char *s = new char[tamanho_total];
    s[0] = '\0';
    strcat(s, texto1);
    strcat(s, texto2);
    return Texto(s);
}

int main() {
    Texto t1("um teste");
    Texto t2(" e outro teste!");
    Texto t3 = t1+t2;
    
    cout << t1.gettexto() << endl;
    cout << t2.gettexto() << endl;
    cout << t3.gettexto() << endl;
        
    system("pause");
}

Os comentários no código indicam o ponto crucial (e acho que é a parte em que você está com dúvida).

Qualquer coisa, 'stamos aí. wink.gif

Graymalkin

Link para o comentário
Compartilhar em outros sites

  • 0

Eu sou chato, ne gray, rsrs, fala serio, mas fazer o que se eu gosto do negocio, rsrs. Bem, olhe essa parte:

Texto t3 = t1+t2
Ate ai tudo bem, ela chama a sobrecarga, que e essa parte:
Texto Texto::operator+(Texto t) {
   char *texto1 = this->gettexto(); // Texto *deste* (this) objeto
   char *texto2 = t.gettexto(); // Texto do objeto passado 

Bem, no caso, aquele parametro t, esta chamando o objeto t2 ou t1? não deveria chamar t2, aqui ele esta chamando t1.

Link para o comentário
Compartilhar em outros sites

  • 0

Eu sou chato, ne gray, rsrs, fala serio, mas fazer o que se eu gosto do negocio, rsrs. Bem, olhe essa parte:

Texto t3 = t1+t2
Ate ai tudo bem, ela chama a sobrecarga, que e essa parte:
Texto Texto::operator+(Texto t) {
   char *texto1 = this->gettexto(); // Texto *deste* (this) objeto
   char *texto2 = t.gettexto(); // Texto do objeto passado 
Bem, no caso, aquele parametro t, esta chamando o objeto t2 ou t1? não deveria chamar t2, aqui ele esta chamando t1.
Não está *chamando* ninguém, ele é t2. Ou seja, no lugar de...
Texto t3 = t1+t2
... é como se estivesse:
Texto t3 = t1.operator+(t2)

Ou seja, substitua o operador (+) pelo método (operator+) e você entenderá melhor. Uma sobrecarga de operador nada mais é do que um método com um nome especial ("operator" seguido do operador real) e que substitui a utilização de um operador no código. É como se você dissesse o seguinte para o compilador: "ei, quando você achar o sinal de + realizando uma soma entre o objeto tal e outro objeto, chame o método operator+ do primeiro objeto." Sacou agora? wink.gif

Abraços,

Graymalkin

Link para o comentário
Compartilhar em outros sites

  • 0

SIm, to começando a enteder, mas posso te pedir um favorzaço? esse this ta acabando comigo, eu não consigo entender ele, tem como se repassa o codigo sem ele, substituindo pelo objeto? Se você puder eu agradeço, hein gray, valeu mesmo!

Link para o comentário
Compartilhar em outros sites

  • 0
SIm, to começando a enteder, mas posso te pedir um favorzaço? esse this ta acabando comigo, eu não consigo entender ele, tem como se repassa o codigo sem ele, substituindo pelo objeto? Se você puder eu agradeço, hein gray, valeu mesmo!

O this é simplesmente uma maneira de você se referir ao objeto estando dentro dele mesmo. Esse this é a mesma coisa do Me em VB, do this em Java e C#, e do Self em Delphi e Python, por exemplo. Quando você está pensando consigo mesmo, com seus botões, e você quer se referir a você mesmo, você não se chama pelo seu nome ou algum apelido? É isso que é o this dentro da classe. Aquele mesmo código pode ser escrito sem o this e vai ser a mesma coisa:

#include <stdlib.h>
#include <iostream>
#include <string.h>

using namespace std;

class Texto {
     private:
            char *texto;
     public:
            Texto(char *s);
            char *gettexto();
            Texto operator+(Texto t);
};

Texto::Texto(char *s) {
   texto = s;
}

char *Texto::gettexto() {
   return texto;
}

Texto Texto::operator+(Texto t) {
   char *texto1 = gettexto(); // Texto *deste* objeto
   char *texto2 = t.gettexto(); // Texto do objeto passado
   // Percebe agora os dois elementos a serem "somados"?
   
   int tam1 = strlen(texto1);
   int tam2 = strlen(texto2);
   int tamanho_total = tam1+tam2+1;

   char *s = new char[tamanho_total];
   s[0] = '\0';
   strcat(s, texto1);
   strcat(s, texto2);
   return Texto(s);
}

int main() {
   Texto t1("um teste");
   Texto t2(" e outro teste!");
   Texto t3 = t1+t2;
   
   cout << t1.gettexto() << endl;
   cout << t2.gettexto() << endl;
   cout << t3.gettexto() << endl;
       
   system("pause");
}

Veja que não muda nada... apenas o this não aparece.

Abraços,

Graymalkin

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,4k
×
×
  • Criar Novo...