una son que programacion privado privada otra modificadores modificador metodo los desde definicion cuales como clase acceso acceder c++ class inheritance interface

son - C++: ¿Derivado+clase base implementa una sola interfaz?



que es private en c++ (5)

En C ++, ¿es posible tener una base más una clase derivada que implemente una sola interfaz?

Por ejemplo:

class Interface { public: virtual void BaseFunction() = 0; virtual void DerivedFunction() = 0; }; class Base { public: virtual void BaseFunction(){} }; class Derived : public Base, public Interface { public: void DerivedFunction(){} }; void main() { Derived derived; }

Esto falla porque no se puede crear una instancia de Derived. En lo que respecta al compilador, Interface :: BaseFunction nunca se define.

Hasta ahora, la única solución que he encontrado sería declarar una función de transferencia en Derivado

class Derived : public Base, public Interface { public: void DerivedFunction(){} void BaseFunction(){ Base::BaseFunction(); } };

¿Hay alguna solución mejor?

EDITAR: Si importa, aquí hay un problema del mundo real que tuve al usar cuadros de diálogo MFC.

Tengo una clase de diálogo (MyDialog digamos) que se deriva de CDialog. Debido a problemas de dependencia, necesito crear una interfaz abstracta (MyDialogInterface). La clase que usa MyDialogInterface necesita usar los métodos específicos de MyDialog, pero también necesita llamar a CDialog :: SetParent. Lo resolví creando MyDialog :: SetParent y haciéndolo pasar a CDialog :: SetParent, pero me preguntaba si habría una forma mejor.


El problema es que con su ejemplo, tiene dos implementaciones de Interface , la que viene de Base y la que viene de Derived . Esto es por diseño en el lenguaje C ++. Como ya se señaló, simplemente elimine la clase base de la Interface en la definición de Derived .


Estoy de acuerdo con la respuesta por litb. Sin embargo, aquí hay una oportunidad para entender algo sobre cómo funcionan las funciones virtuales y la herencia múltiple.

Cuando una clase tiene múltiples clases base, tiene tablas virtuales separadas para cada clase base. Derived tendrá una estructura vtable que se ve así:

Derived vtable: Interface BaseFunction* DerivedFunction* vtable: Base BaseFunction*

Además, cada clase base solo podrá ver su propia tabla virtual. Cuando Base se crea una instancia, rellena el puntero Base::BaseFunction en el vtable, pero no puede ver el vtable para Interface.

Si el código que proporcionó pudiera compilarse, la estructura vtable resultante de una instancia de Derived se vería así:

Derived vtable: Interface BaseFunction* = 0 DerivedFunction* = Derived::DerivedFunction vtable: Base BaseFunction* = Base::BaseFunction


Parece que no es exactamente el caso de que Derived "is-a" Base, lo que sugiere que la contención puede ser una mejor implementación que la herencia.

Además, las funciones de miembros derivados también se deben calificar como virtuales.

class Contained { public: void containedFunction() {} }; class Derived { public: virtual void derivedFunction() {} virtual void containedFunction() {return contained.containedFunction();} private: Containted contained; };

Puede hacer que el miembro contenido sea una referencia o un puntero inteligente si desea ocultar los detalles de implementación.


C ++ no nota que la función heredada de Base ya implementa BaseFunction : la función debe implementarse explícitamente en una clase derivada de Interface . Cambiarlo de esta manera:

class Interface { public: virtual void BaseFunction() = 0; virtual void DerivedFunction() = 0; }; class Base : public Interface { public: virtual void BaseFunction(){} }; class Derived : public Base { public: virtual void DerivedFunction(){} }; int main() { Derived derived; }

Si quieres ser capaz de salirte con la suya solo implementando uno de ellos, Interface en dos interfaces:

class DerivedInterface { public: virtual void DerivedFunction() = 0; }; class BaseInterface { public: virtual void BaseFunction() = 0; }; class Base : public BaseInterface { public: virtual void BaseFunction(){} }; class Derived : public DerivedInterface { public: virtual void DerivedFunction(){} }; class Both : public DerivedInterface, public Base { public: virtual void DerivedFunction(){} }; int main() { Derived derived; Base base; Both both; }

Nota: main debe devolver int
Nota: es una buena práctica mantenerse virtual frente a las funciones miembro en los derivados que eran virtuales en la base, incluso si no es estrictamente necesario.


Encontré una cosa que falta en la respuesta de Litb. Si tengo una instancia Derived , puedo obtener una DerivedInterface y BaseInterface . Pero si solo tengo una DerivedInterface no puedo obtener una BaseInterface porque derivar DerivedInterface de BaseInterface no funcionará.

Pero, todo este tiempo, me he estado limitando a recopilar el tiempo comprobando por alguna razón. Esta DerivedInterface funciona muy bien:

class DerivedInterface { public: virtual void DerivedFunction() = 0; BaseInterface* GetBaseInterface() {return dynamic_cast<BaseInterface*>(this);} }; void main() { Derived derived; DerivedInterface* derivedInterface = &derived; derivedInterface->GetBaseInterface()->BaseFunction(); }

No se pasan las funciones necesarias en Derived, y todos están felices. Claro, ya no es estrictamente una interfaz, pero está bien. ¿Por qué no pensé en eso antes? :)