El problema que está experimentando está relacionado con la forma en la búsqueda de nombres funciona en C++. En particular, al resolver un miembro, el compilador examinará el tipo estático del objeto al que se está accediendo al miembro. Si el identificador se encuentra en esa clase, la búsqueda se completa y (en el caso de las funciones miembro) se inicia la resolución de sobrecarga. Si no se encuentra el identificador, se arrastrará por la jerarquía, clase por clase, tratando de localizar el identificador un nivel a la vez.
En su caso particular, tiene c->onFoo();
y c
es del tipo C
. El compilador no ve ninguna declaración de onFoo
en C
, por lo que continúa hacia arriba en la jerarquía. Cuando el compilador comprueba B
, ve que hay una declaración de void onFoo(int i)
en ese nivel, por lo que detiene la búsqueda e intenta la resolución de sobrecarga. En este momento, la resolución de sobrecarga falla debido a la inconsistencia en los argumentos.
El hecho de que una declaración de void onFoo(int)
está presente en B
nivel tiene el efecto de ocultar el resto de las sobrecargas en cualquier clase de base, ya que dejará de búsqueda. Tenga en cuenta que este es un problema con la búsqueda no calificada, la función todavía está allí y es aplicable al objeto, pero no se encontrará mediante la búsqueda regular (todavía puede llamarlo como c->A::onFoo()
).
A partir de cómo hacer frente a ocultar, la forma más sencilla es mediante el empleo de la declaración using para llevar las funciones en el alcance:
class B : A {
public:
using A::onFoo; // All A::onFoo overloads are *considered* here
void onFoo(int);
};
El efecto de la declaración using
aquí es que cuando la clase B
se busca, en la búsqueda del identificador onFoo
, se indica al compilador que también considere todas las sobrecargas de onFoo
en la clase base, permitiendo la búsqueda regular para encontrar A::onFoo()
.
+1 - Buena explicación. – Mahesh