Estoy usando pseudo-interfaces en C++, es decir, clases abstractas puras. Supongamos que tengo tres interfaces, IFoo, IBar e IQuux. También tengo una clase que implementa Fred los tres de ellos:Comprobación de la implementación de la interfaz en tiempo de compilación en C++
interface IFoo
{
void foo (void);
}
interface IBar
{
void bar (void);
}
interface IQuux
{
void quux (void);
}
class Fred : implements IFoo, IBar, IQuux
{
}
Quiero declarar un método que acepta cualquier objeto que implemente IFoo y IBar - un Fred quiere trabajar, por ejemplo. La única forma de tiempo de compilación para hacer esto que puedo imaginar es definir una tercera IFooAndBar interfaz que implementa ambos, y redeclare Fred:
interface IFooAndBar : extends IFoo, IBar
{
}
class Fred : implements IFooAndBar, IQuux
{
}
Ahora puedo declarar mi método como la recepción de un IFooAndBar *. Hasta aquí todo bien.
Sin embargo, ¿qué ocurre si quiero también un método diferente que acepte Ibar y IQuux? He intentado declarar una nueva interfaz IBarAndQuux y declarando como Fred heredar tanto:
class IFooAndBar : IFoo, IBar
{
};
class IBarAndQuux : IBar, IQuux
{
};
class Fred : IFooAndBar, IBarAndQuux
{
};
Esto funciona cuando paso Fred como IFooAndBar a un método; Sin embargo, cuando trato de llamar a Fred :: bar() directamente, gcc se queja:
error: request for member ‘bar’ is ambiguous
error: candidates are: void IBar::bar()
error: void IBar::bar()
lo que hace que esta solución más o menos inútil.
Mi siguiente intento fue declarar Fred como la herencia de las tres interfaces individuales, y hacer que el método de aceptar una de las interfaces híbridos como un parámetro:
class Fred : public IFoo, public IBar, public IBaz
{
};
void doTest (IBarAndBaz* pObj)
{
pObj->bar();
pObj->baz();
}
Cuando trato de pasar Fred como el IBarAndBaz parámetro *, me sale un error, como se esperaba:
error: cannot convert ‘Fred*’ to ‘IBarAndBaz*’ for argument ‘1’ to ‘void doTest(IBarAndBaz*)’
dynamic_cast <> también p roduces un error (que no entiendo)
error: cannot dynamic_cast ‘pFred’ (of type ‘class Fred*’) to type ‘class IBarAndBaz*’ (source type is not polymorphic)
Forzar a un elenco qué trabajo, sin embargo:
doTest((IBarAndBaz*)pFred);
pero me pregunto qué tan seguro y portátil que es (que desarrollo para Linux, Mac y Windows), y si funciona en una situación del mundo real.
Por último, se dan cuenta de mi método puede aceptar un puntero a una de las interfaces y dynamic_cast al otro (s) para hacer cumplir el tipo de parámetro correcto en tiempo de ejecución, pero yo prefiero una solución en tiempo de compilación.
No es seguro y es portable. De hecho, no está definido en C++. –