Describir en detalle las diversas sobrecargas de operadores en C++

1. Sobrecarga de operadores iguales

A lo que debemos prestar atención es que cuando no sobrecargamos el operador de signo igual, el sistema generará la sobrecarga del operador de signo igual en forma de asignación superficial por defecto. La llamada asignación superficial es para asignar directamente las propiedades del miembro. del objeto de destino al objeto actual (consulte copia profunda) y copia superficial, explicada en detalle en mi artículo "C++ - Explicación del constructor de copias").

Object 
{
    
    
public:
//其他的构造函数、析构函数不是本篇文章重点,省略。
    void operator=(const Object& obj)
    {
    
    
         this->value=obj.value;
    }
    /*
    在主函数中使用obja=objb=objc,等价于下面的方法调用:
    obja=objb.operator=(objc);
    obja=operator=(&objb,objc);
    */
private:
    int value;
}

Los siguientes tres puntos deben explicarse para la declaración de asignación anterior:
① Esta declaración de asignación no se puede modificar con const, porque este->valor cambia en el proceso de asignación
② Este método no puede implementar la asignación continua, porque el valor de retorno es nulo, puede usar Si void se cambia a Objeto, se puede realizar una asignación continua.③
Dado que el objeto está en la función principal, ingresa al método actual por referencia, por lo que el objeto obj no se ve afectado por el período de llamada de esta función sobrecargada, para que pueda ser devuelto por referencia

Hay dos casos de sobrecarga del operador de signo igual:
① No hay ningún tipo ni objeto diseñado por usted mismo, los cuales son tipos básicos, luego el sistema capturará las direcciones de atributo de miembro de los dos objetos e importará directamente los datos del atributo de miembro del objeto de destino en las propiedades de miembro de objeto actual.
② Si hay más que tipos básicos en las propiedades de los miembros, si no sobrecargamos el operador de signo igual, el sistema generará una declaración de asignación superficial predeterminada.

2, más sobrecarga del operador

class Int
{
    
    
private:
   int value;
public:
    //前置加加
   Int& operator++()
   {
    
    
       this->value+=1;
       return *this;
   }
    //后置加加
   Int operator++(int)
   {
    
    
       Int tmp = *this;
       ++* this;//调用前置加加
       return tmp;
   }
    //对象+对象
   Int operator+(Int& b)const
   {
    
    
       Int c;
       c.value   = this->value + b.value;
       return c;
   }
    //对象+数值
   Int operator+(int val)const
   {
    
    
       Int c;
       c.value = this->value + val;
       return c;
   }
   
};
//数值+对象
Int operator+(const int val, const Int& a)
{
    
    
    return a + val;//调用Int operator+(int val)const 这个方法
}

3. Sobrecargar el operador de dirección

class Int
{
    
    
private:
   int value;
public:
   //省略构造函数、等号运算符重载,这里主要说明取地址运算符重载
   Int* operator&()
   {
    
    
        return this;
   }
   const Int* operator&()const//加了const的取地址运算符重载是一个常方法
   {
    
    
        return this;
   }
}
int main()
{
    
    
    Int a(10);
    Int b=10;//这句话会先调用构造函数构造一个value成员属性为10的对象,然后把这个对象赋值给b
    const Int c=10;
    const Int *ip=&c;//因为C是常对象,所以就会调用上面的常方法
}

4, sobrecarga del operador pre-++, post-++

4.1 Problema de referencia posterior a ++:

Debido a que es post ++, como se puede ver en el siguiente código, necesitamos crear un objeto para guardar el valor original y luego agregar el valor actual en 1. Sin embargo, la vida útil del objeto creado y el método de anulación el método post ++ Al igual que la vida útil, cuando finaliza la llamada a la función, se libera el espacio. Así que no puedes devolver una referencia.

 //后置加加
   Int operator++(int)
   {
    
    
       Int tmp = *this;
       ++* this;//调用前置加加
       return tmp;
   }

Pero si tenemos que devolver una referencia, ¿podemos agregar una estática? como sigue:

Int& operator++(int)
{
    
    
    static Int old=*this;
    ++* this;
    return old;
}

Debido a que el código anterior se define como estático, no hay problema cuando ejecutamos post ++ una vez, pero debido a que es estático, solo ejecutamos static Int old=*this; una vez, cuando ejecutamos post ++ nuevamente, el valor no no cambia, ni el valor anterior, entonces lo cambiamos por el siguiente:

Int& operator++(int)
{
    
    
    static Int old=*this;
    old=*this;
    ++* this;
    return old;
}

Después de agregar la oración old=*this, cada vez que ejecutamos el método post-add, la variable estática old se reasignará al objeto actual, evitando así el mencionado "cuando el post-add ++ se ejecute nuevamente, el valor no cambia, es el mismo valor que antes".
Un ejemplo para ilustrar el código modificado:
inserte la descripción de la imagen aquí
la última salida d es 12, porque old=*this; actualizará old.

4.2 Análisis de problemas relacionados

Combinado con la siguiente sobrecarga de operadores, analice el código de Int a=0;a=a++ +1;.

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

5, operador de fundición de tipo sobrecargado

(1) Conversión de tipo implícita:
La llamada conversión de tipo implícita se explica con el siguiente ejemplo:
a=b, esta oración en realidad se construye primero con el valor del entero b, y asigna el objeto construido a a, Después de la función principal finaliza la llamada, este objeto se destruye y a se destruye.
(Palabras clave que no permiten conversiones implícitas: explícitas)

Debe enfatizarse que un constructor capaz de conversión implícita de tipo debe ser un solo parámetro
inserte la descripción de la imagen aquí

(2) Conversión de tipo de coerción:
el objeto se fuerza a un tipo incorporado

//把对象强转成整型
operator int() const
{
    
    
    return value;
} 

El tipo devuelto por la coerción es el tipo después de la coerción, por lo que la función sobrecargada no necesita establecer el tipo de retorno
Por ejemplo, lo siguiente: Si se devuelve flot, entrará en conflicto con el tipo de retorno.
inserte la descripción de la imagen aquí

6. Sobrecarga del operador de paréntesis

class Add
{
    
    
      mutable int value;//加了mutable这个关键字之后,可以让value这个变量在常方法中也能改变
 public:
       Add(int x=0):value(x){
    
    };
       int operator()(int a,int b)const//括号运算符重载
       {
    
     
            value=a+b;
            return value;
       } 
}
int main()
{
    
    
    int a=10,b=20,c=0;
    Add add;
    c=add(a,b);//调用括号运算符重载,我们也称之为仿函数
    //c=add.operator()(a,b);
    return 0;
}

7. Sobrecarga del operador de salida

La siguiente sobrecarga del operador de salida es incorrecta. El parámetro out debe llamarse por referencia. Debido a que el código del sistema establece un flujo de salida privado, debe ser una llamada de referencia. Si no es una llamada de referencia, se llamará a la construcción de copia, y la construcción de copia se establece en privado y no se puede llamar

class String
{
    
    
private:
      char * str;
public:
      //ostream& operator<<(const String* const this,ostream& out)
      ostream& operator<<(ostream out)const
      {
    
    
           if(str!=NULL)
           {
    
    
                out<<str;
           }
           return out;
      }
      //s1<cout
      //s1.operator<<(cout)
      //operator(&s1,cout)
}

El correcto es el siguiente:
escribe el contenido de str en la colocación y devuélvelo
inserte la descripción de la imagen aquí
. Pero la sobrecarga del operador de salida anterior es: s1<<cout, que no se ajusta a nuestra sobrecarga del operador de salida lógica:
entonces:
llama al operador ostream& < <(ostream& out, const String& s)
y luego llame al operador de salida sobrecarga dentro del objeto

class String
{
    
    
private:
      char * str;
public:
      //ostream& operator<<(const String* const this,ostream& out)
      ostream& operator<<(ostream& out)const
      {
    
    
           if(str!=NULL)
           {
    
    
                out<<str;
           }
           return out;
      }
      //s1<cout
      //s1.operator<<(cout)
      //operator(&s1,cout)
}
ostream& operator<<(ostream& out,const String& s)
{
    
    
    s<<out;
    //s.operator<<(out);
    //operator<<(&s,out);
    return out;
} 
int main()
{
    
    
     String s1("hello world");
     cout<<s1<<endl<<;
     return 0;
}

8. Sobrecarga del operador Asterisco

class Int
{
    
    
private:
     int value;
};
class Object
{
    
    
    Int* ip;//Int是一个类
public:
    Object(Int* s=NULL):ip(s){
    
    }
    ~Object()
    {
    
    
         if(ip!=NULL)
         {
    
    
              delete ip;
         }
         ip=NULL;
    }
    //✳运算符重载返回这个对象所指向的地址
    Int* operator*()
    {
    
    
        return ip;
    }
    const Int* operator*()const
    {
    
    
        return ip;
    }
    //✳运算符重载返回ip所指向的对象
    Int& operator*()
    {
    
    
        return *ip;
    }
    const Int& operator*()const
    {
    
    
        return *ip;
    }
};
int main()
{
    
    
     Object obj(new Int(10));
     (*obj)->value();
}

9. Sobrecarga del operador puntero

class Int
{
    
    
private:
     int value;
};
class Object
{
    
    
    Int* ip;//Int是一个类
public:
    Object(Int* s=NULL):ip(s){
    
    }
    ~Object()
    {
    
    
         if(ip!=NULL)
         {
    
    
              delete ip;
         }
         ip=NULL;
    }
    //返回所指向的这个对象的地址
    const Int* operator->()const
    {
    
    
        return ip;
    }
}
int main()
{
    
    
     Object obj(new Int(10));
     obj->value();
}

Nota: El problema del "uso libre de objetos" se realiza mediante el uso combinado de la sobrecarga del operador asterisco y la sobrecarga del operador señalador: El
problema presenta:

class Int
{
    
    
private:
     int value;
};
class Object
{
    
    
    Int* ip;//Int是一个类
public:
    Object(Int* s=NULL):ip(s){
    
    }
    ~Object()
    {
    
    
         if(ip!=NULL)
         {
    
    
              delete ip;
         }
         ip=NULL;
    }
    Int& operator*()//重载*,返回ip所指对象本身
    {
    
    
         return *ip;
    }
    const Int& operator*()const
    {
    
    
         return *ip;
    }
    Int* operator->()
    {
    
    
         return &**this;
    }
    const Int* operator->()const
    {
    
    
         return &**this;
         //return ip
    }
}

¿Qué significa &**esto anterior?

Para el código anterior, lo analizamos de derecha a izquierda en combinación con la siguiente figura: esto se refiere al objeto obj, * esto indica el objeto obj, y luego ** esto llama a la sobrecarga del operador ✳, que indica el objeto al que apunta ip en sí, por lo que este conjunto representa la dirección del objeto al que apunta ip.
inserte la descripción de la imagen aquí
Por lo tanto, después de ingresar el operador ✳ y el operador ->, también se puede obtener el objeto Int, y el formulario Obj se usa para lograr la liberalización, es decir, en el destructor En este momento, el espacio del montón al que apunta ip se destruirá automáticamente, y no necesitamos liberarlo manualmente.

Supongo que te gusta

Origin blog.csdn.net/m0_54355780/article/details/122638113
Recomendado
Clasificación