c++ - Herencia por dominio: ¿es realmente malo?
visual-c++ diamond-problem (3)
Soy una de esas personas que tiene que obtener su código para compilar con 0 advertencias. Normalmente respeto el compilador y si me emite una advertencia lo tomo como una señal de que debo retocar un poco mi código. Si tengo que decirle a un compilador que ignore una advertencia dada, me muevo un poco.
Pero este no puedo entenderlo, y por lo que puedo decir, no he hecho nada "malo". ¿Alguien piensa que este es un diseño pobre? No puedo ver nada particularmente desagradable al respecto (excepto el "diamante malvado"), pero es un código perfectamente válido y útil. ¡Pero genera (en MSVC) una advertencia de nivel 2!
class IFoo
{
public:
virtual void foo() = 0;
};
class Bar : public virtual IFoo
{
public:
virtual void foo() { std::cout << "Hello, world!"; }
};
class Baz : public virtual IFoo
{
};
class Quux : public Bar, public Baz
{
};
Ahora, si creo un objeto Quux, se espera que invoque la implementación Bar :: foo. MSVC es muy útil: ¿me advierte por no ser lo suficientemente ambiguo?
Advertencia C4250: ''Quux'': hereda ''Bar :: Bar :: foo'' a través de la dominación
Ahora reconozco que puedo desactivar esta advertencia con un pragma, pero esa no es la pregunta que trato de hacer aquí. ¿Hay alguna razón por la que debería estar escuchando el compilador aquí, o es solo una advertencia extremadamente exagerada?
Al realizar la herencia virtual, es una mala idea no anular explícitamente a todos los miembros en la clase más derivada. De lo contrario, estás pidiendo que tu código tenga una muerte horrible cuando alguien cambia una de tus clases base que hereda de la base virtual. No hay nada activamente malo en esto, su programa no fallará o no funcionará, pero es una mala idea para el mantenimiento. Si desea llamar a la versión de Bar::foo
, simplemente debe delegar en Quux::foo
.
En cuanto a la viabilidad de su código, está allí para recordarle que Bar es la implementación dominante de foo
. Está ahí para informarle, no es realmente una advertencia, por lo que si está depurando y cree que es Baz
, no se jala el pelo :).
¿Hay alguna razón por la que no estás escribiendo?
class Quux : public Bar, public Baz
{
using Bar::foo;
};
?
Esto le da el mismo nivel de reutilización, sin la fragilidad.