Programação C/C++
Prof. Márcio Sarroglia Pinho

Sobrecarga de Operadores com Classes ou Structs

A sobrecarga de um operador deve ser feita criando-se uma função ou método cujo nome deve iniciar pela palavra operator. Por exemplo, para sobrecarregar o comportamento do operador de soma o nome da função/método seria operator+, para sobrecarregar o operador ">" a função seria operator>.

Sobrecarga com funções FORA
de classes/structs

Quando a sobrecarga for feita com uma função, ou seja, fora de uma classe, esta função deverá ter 2 parâmetros caso o operador seja binário e 1 parâmetro caso o operador seja unário.

No caso de um operador BINÁRIO, como o de multiplicação(*), o primeiro parâmetro desta função representará o operando que fica à
esquerda do operador e o segundo
representará o operando que fica à direita.
No exemplo abaixo, o operador + é sobrecarregado através de uma função, para operar sobre dois objetos da classe PONTO. O tipo do retorno da função deve corresponder ao tipo de dados a ser gerado pela operação. O tipo deste retorno pode ser inclusive void, caso o operador nada retorne.

PONTO operator+ (PONTO &p1, PONTO &p2)
{
    PONTO temp;
  temp.setX(p1.getX()+p2.getX());    
  temp.setY(p1.getY()+p2.getY()); 
  return temp; 
}

No caso de um operador UNÁRIO, como o de !, o primeiro parâmetro desta função representará o operando que fica à direita do operador. No exemplo abaixo, o operador ! é sobrecarregado através de uma função, para zerar os atributos de objetos da classe PONTO. Neste caso o retorno é void, mas poderia ser de outro tipo caso fosse necessário.

void operator! (PONTO &p1)
{
    PONTO temp;
  p1.setX(0);    
  p1.setY(0); 
 
}


Sobrecarga com funções DENTRO de classes/structs

Quando a sobrecarga for feita com um método de uma classe, esta função deverá ter 1 parâmetro caso o operador seja binário e nenhum parâmetro caso o operador seja unário.

No caso de um operador BINÁRIO, como o de multiplicação(*), o parâmetro desta função representará o operando que fica à
direita do operador. O operando que fica à esquerda é representado pelos atributos da classe.
No exemplo abaixo, o operador + é sobrecarregado através de um método, para operar sobre dois objetos da classe PONTO. O tipo do retorno da função deve corresponder ao tipo de dados a ser gerado pela operação.

PONTO PONTO::operator+ (PONTO &v1)
{
    PONTO temp;
    temp.x = v1.x + x;
    temp.y = v1.y + y;
    return temp;
}

No caso de um operador UNÁRIO, como o de !, o método não terá parâmetros, sendo que os atributos da classe é que representarão o operando que fica à direita do operador. No exemplo abaixo, o operador ! é sobrecarregado através de um método para zerar os atributos de objetos da classe PONTO. Neste caso o retorno é void, mas poderia ser de outro tipo caso fosse necessário.

void PONTO::operator! ()
{
  setX(0);    
  setY(0); 
}

Sobrecarga com COUT e CIN

Um dos usos mais comuns de sobrecarga de operadores é com os operadores << e >> junto com os objetos cout e cin, respectivamente.

Para tanto é necessário saber que o objeto cout é um objeto da classe
ostream e que o cin é um objeto da classe istream. No techo de código abaixo, os dois operadores sõa sobrecarregados para operarem com objetos da classe/struct PONTO.

ostream& operator<<(ostream &Saida, PONTO &p)
{
    cout << "X: " << p.getX() << " " <<
"Y: " << p.getY() ;
    return
Saida;
}

istream& operator>>(istream &Entrada, PONTO &p)
{
    int i;
    cin >> i;
    p.setX(i);
    cin >> i;
    p.setY(i);
    return
Entrada;

}


EXEMPLOS

No exemplo abaixo alguns atributos são sobrecarregados para objetos da struct PONTO.

// Define um tipo de dados novo
typedef struct PONTO{
        int x,y;
        PONTO operator+ (PONTO &v1);
        PONTO operator* (PONTO &v1);
        PONTO operator- (PONTO &v1);
        PONTO operator- ();   // menos Unário
        void operator= (int n);  // atribuicao
        void operator! (); // impressao
        void Imprime();
        } PONTO;

void PONTO::operator! ()
{
    printf("(%d,%d)", x,y);
}

void PONTO::operator= (int n)
{
       x = n;
       y = n;
}

PONTO PONTO::operator+ (PONTO &v1)
{
       PONTO temp;
       temp.x = v1.x + x;
       temp.y = v1.y + y;
       return temp;
}

PONTO PONTO::operator* (PONTO &v1)
{
       PONTO temp;
       temp.x = v1.x * x;
       temp.y = v1.y * y;
       return temp;
}

PONTO PONTO::operator- (PONTO &v1)
{
       PONTO temp;
       temp.x = x - v1.x;
       temp.y = y - v1.y;
       return temp;

}
PONTO PONTO::operator-()
{
       PONTO temp;
       temp.x = -x;
       temp.y = -y;
       return temp;

}

int main(int argc, char *argv[])
{
    PONTO a = {5,4},
           b = {6,2},
           c;          
          
       
    cout << "Subtracao" << endl;
    c = b-a;                 
    //c.Imprime();
    !c;
    cout << "Troca de Sinal" << endl;
    c = -c;
    c.Imprime();
    cout << "Soma" << endl;
    c = a+b;
    c.Imprime();
    cout << "Multiplicacao" << endl;
    c = a * a * a;
    c.Imprime();   

    cout << "Atribuicao" << endl;
    c = 3;
    c.Imprime();

    return 0;
   
}



Lista de Operadores que podem ser sobrecarregados
 
Operadores  Unários
+  -  *  &  ~  !  ++  --  ->  ->*


Operadores Binários
 
+  -  *  /  %  ^  &  |  <<  >> 
+= -= *= /= %= ^= &= |= <<= >>= 
<  <=  >  >=  ==  !=  &&  || 
,  []  () 
new  new[]  delete  delete[]