sobreescritura sobrecarga programacion polimorfismo operadores metodos herencia conclusion c++ scope overloading multiple-inheritance

c++ - programacion - sobrecarga de operadores en java



¿Por qué las funciones heredadas múltiples con el mismo nombre pero diferentes firmas no se tratan como funciones sobrecargadas? (3)

¿Funcionará para ti?

struct Derived : public Base1, public Base2{ using Base2::foo;}

El siguiente fragmento produce un error de "llamada ambigua a foo" durante la compilación, y me gustaría saber si hay alguna forma de solucionar este problema sin calificar completamente la llamada a foo:

#include <iostream> struct Base1{ void foo(int){ } }; struct Base2{ void foo(float){ } }; struct Derived : public Base1, public Base2{ }; int main(){ Derived d; d.foo(5); std::cin.get(); return 0; }

Entonces, la pregunta es como dice el título. Ideas? Es decir, lo siguiente funciona a la perfección:

#include <iostream> struct Base{ void foo(int){ } }; struct Derived : public Base{ void foo(float){ } }; int main(){ Derived d; d.foo(5); std::cin.get(); return 0; }


Las reglas de búsqueda de miembros se definen en la Sección 10.2 / 2

Los siguientes pasos definen el resultado de búsqueda de nombre en un alcance de clase, C Primero, se considera cada declaración para el nombre en la clase y en cada uno de sus sub-objetos de clase base. Un nombre de miembro f en un subobjeto B oculta un nombre de miembro f en un subobjeto A si A es un subobjeto de clase base de B Cualquier declaración que esté tan oculta se elimina de la consideración . Cada una de estas declaraciones que fue introducida por una declaración de uso se considera que proviene de cada subobjeto de C que es del tipo que contiene la declaración designada por la declaración de uso. Si el conjunto resultante de declaraciones no provienen todas de subobjetos del mismo tipo, o el conjunto tiene un miembro no estático e incluye miembros de distintos subobjetos, existe una ambigüedad y el programa está mal formado . De lo contrario, ese conjunto es el resultado de la búsqueda.

class A { public: int f(int); }; class B { public: int f(); }; class C : public A, public B {}; int main() { C c; c.f(); // ambiguous }

Entonces puede usar las declaraciones de using A::f y B::f para resolver esa ambigüedad

class C : public A, public B { using A::f; using B::f; }; int main() { C c; c.f(); // fine }

El segundo código funciona sin problemas porque void foo(float) está dentro del alcance de C. En realidad d.foo(5); llama a void foo(float) y no a la versión int .


La búsqueda de nombres es una fase separada para sobrecargar la resolución .

La búsqueda de nombre ocurre primero. Ese es el proceso de decidir a qué alcance se aplica el nombre. En este caso, debemos decidir si d.foo significa d.foo dD::foo , o d.B1::foo , o d.B2::foo . Las reglas de búsqueda de nombre no tienen en cuenta los parámetros de la función ni nada; es puramente sobre nombres y alcances.

Una vez que se ha tomado esa decisión, se realiza una resolución de sobrecarga en las diferentes sobrecargas de la función en el ámbito donde se encontró el nombre.

En su ejemplo, al llamar a d.foo() encontraría D::foo() si existiera dicha función. Pero no hay ninguno. Entonces, trabajando hacia atrás en los ámbitos, prueba las clases base. Ahora foo también podría buscar B1::foo o B2::foo por lo que es ambiguo.

Por la misma razón, obtendría ambigüedad llamando a foo(5); no calificado foo(5); dentro de una función de miembro D

El efecto de la solución recomendada:

struct Derived : public Base1, public Base2{ using Base1::foo; using Base2::foo;

es que esto crea el nombre D::foo , y lo hace identificar dos funciones. El resultado es que d.foo resuelve d.foo dD::foo , y luego puede ocurrir una resolución de sobrecarga en estas dos funciones identificadas por D::foo .

Nota: En este ejemplo, D::foo(int) y Base1::foo(int) son dos identificadores para una función; pero en general, para el proceso de búsqueda de nombre y resolución de sobrecarga, no importa si son dos funciones separadas o no.