¿Por qué anular tanto el nuevo operador global como el operador específico de clase no es ambiguo?

La siguiente sección trata sobre la resolución de sobrecarga, ya que ayuda en los fundamentos de la sobrecarga y la anulación.
Predecir la salida:

#include <iostream>
using namespace std;
  
class Gfg {
public:
    void printHello()
    {
        cout << "hello gfg-class specific" << endl;
    }
};
  
void printHello()
{
    cout << "hello gfg-global" << endl;
}
int main()
{
    Gfg a;
    a.printHello();
    printHello();
}
Output:
hello gfg-class specific
hello gfg-global

¿Cómo diferencia el compilador la función específica de clase y una función global?
Para mapear la llamada de función con la definición de función correspondiente, el compilador realiza el proceso de búsqueda de nombre. Este proceso produce un conjunto de funciones que tienen el mismo nombre y se denominan funciones candidatas. Si hay más de una función candidata, el compilador realiza el proceso de búsqueda dependiente del argumento. Si este proceso también arroja más de una función candidata, entonces se lleva a cabo el proceso de resolución de sobrecarga para seleccionar la función que debe llamarse.
Si alguna de las funciones candidatas es una función miembro de la clase correspondiente (estática o no estática), se antepone un parámetro de objeto implícito que representa el objeto para el que se llama y aparece antes del primero de los parámetros reales.

Predecir la salida:

#include <iostream>
using namespace std;
  
class Gfg {
public:
    Gfg operator+(Gfg& a)
    {
        cout << "class specific + operator" << endl;
        return Gfg(); // Just return some temporary object
    }
};
  
Gfg operator+(Gfg& a, Gfg& b)
{
    cout << "global + operator called" << endl;
    return Gfg(); // Just return some temporary object
}
  
int main()
{
    Gfg a, b;
    Gfg c = a + b;
}
Output: Compilation error
plusOverride.cpp: In function ‘int main()’:
plusOverride.cpp:19:9: error: ambiguous overload for ‘operator+’ 
(operand types are ‘Gfg’ and ‘Gfg’)
  Gfg c=a+b;
         ^
plusOverride.cpp:19:9: note: candidates are:
plusOverride.cpp:6:9: note: Gfg Gfg::operator+(Gfg&)
     Gfg operator+(Gfg& a){
         ^
plusOverride.cpp:12:5: note: Gfg operator+(Gfg&, Gfg&)
 Gfg operator+(Gfg& a, Gfg& b){
     ^

Así es como funciona la resolución de sobrecarga con la sobrecarga de operadores:
las funciones candidatas para los operadores binario y unario se seleccionan de diferentes ámbitos. Son
1) candidatos a miembro: El operador funciones sobrecargadas definidas en la clase.
2) Candidatos no miembros: El operador sobrecarga funciones que son globales.
3) candidatos integrados: las funciones integradas que realizan la operación especificada.
Por lo tanto, para el programa anterior durante la compilación, el número de funciones candidatas es más de uno y todas estas funciones candidatas tienen la misma precedencia y, por lo tanto, surge el error de sobrecarga ambiguo.
Predecir la salida:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
  
class Gfg {
public:
    int a;
    void* operator new(size_t sz)
    {
        cout << "class-specific new for size " << sz << '\n';
        return malloc(sz);
    }
  
    void* operator new[](size_t sz)
    {
        cout << "class-specific new[] for size " << sz << '\n';
        return malloc(sz);
    }
};
  
void* operator new[](size_t sz)
{
    cout << "global new[] for size" << sz << '\n';
    return malloc(sz);
}
  
void* operator new(size_t sz)
{
    cout << "global new for size" << sz << '\n';
    return malloc(sz);
}
  
int main()
{
    Gfg* p1 = new Gfg;
    delete p1;
    Gfg* p2 = new Gfg[10];
    delete[] p2;
}
Output: 
class-specific new for size 4
class specific new[] for size 40

El programa funcionó por las siguientes razones:
Los estándares de C++ establecen que “si una clase tiene una función de asignación específica de clase, se llamará a la función, no a la función de asignación global. Esto es intencional: se espera que el miembro de la clase sepa mejor cómo manejar esa clase”. Significa que, cuando la nueva expresión busca la función de asignación correspondiente, comienza en el ámbito de la clase antes de examinar el ámbito global, y si se proporciona la nueva específica de la clase, se invoca. De lo contrario, comprueba el alcance global y lo invoca. Si la nueva función de alcance global no está presente, invocará la nueva función incorporada. De ahora en adelante, las funciones candidatas no tienen la misma precedencia en el ejemplo anterior y, por lo tanto, compila sin ningún error.

¿Puede el programador invocar el operador new global incluso si se define el operador new específico de la clase?
Sí. C++ proporciona el operador de resolución de alcance para ese propósito. Si el operador new está precedido por el operador de resolución de ámbito (::), el compilador busca el operador nuevo en el ámbito global.

¿Qué sucede si el operador new no está definido en el alcance global y está llamando al operador new usando el operador unario ::?
El compilador invocará la nueva función incorporada. El siguiente ejemplo demuestra cómo funciona. Contiene el operador new específico de la clase pero el operador global new. De ahora en adelante, al invocar ::new, el compilador invoca la nueva función de la biblioteca estándar.

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
  
class Gfg {
public:
    int a;
    void* operator new(size_t sz)
    {
        cout << "class-specific new for size " << sz << '\n';
        return malloc(sz);
    }
  
    void* operator new[](size_t sz)
    {
        cout << "class-specific new[] for size " << sz << '\n';
        return malloc(sz);
    }
};
  
void* operator new[](size_t sz)
{
    cout << "global new[] for size " << sz << '\n';
    return malloc(sz);
}
  
int main()
{
    Gfg* p1 = ::new Gfg;
    cout << "Allocated sie of p1: " << sizeof(*p1) << endl;
    delete p1;
    Gfg* p2 = ::new Gfg[10];
    delete[] p2;
}
Output:
Allocated sie of p1: 4
global new[] for size 40

¿Por qué C++ proporciona esta extensibilidad para la nueva función?

  1. Rendimiento: la función de asignación de memoria incorporada es una función de propósito general y se adapta a tipos de datos predefinidos. Para tipos de datos definidos por el usuario que tienen datos muy específicos para asignar, y al personalizar la forma en que se asignan, puede acelerar considerablemente la administración de la memoria.
  2. Depuración y estadísticas: tener el control sobre la forma en que se gasta la memoria proporciona una gran flexibilidad para la depuración, las estadísticas y el análisis de rendimiento.

Estas son algunas de las diversas razones para facilitar la programación mientras se resuelven problemas complejos.

Publicación traducida automáticamente

Artículo escrito por Lokesh Karthikeyan y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *