una reglas publicas protegidas programacion privadas poo orientada objetos miembros hijo herencia enlace ejemplo derivadas derivada definicion clasificacion clases clase bases c++ c++11 inheritance

c++ - publicas - ejemplo de reglas de enlace poo



Cómo prohibir la herencia pública pero permitir la herencia privada(y protegida) (2)

C ++ 11 introdujo la palabra clave final para prohibir futuras anulaciones o para prohibir la herencia. El ejemplo más común donde se puede usar es para el caso de clases que no están destinadas a ser utilizadas como clases base (tienen, por ejemplo, destructores no virtuales). Sin embargo, es posible que en algún momento deseamos tener una relación implementada en términos de dos clases (es decir, herencia private ), y no una relación is-a (herencia public ). Sin embargo, final prohíbe ambos tipos de herencia.

Mi pregunta es la siguiente: ¿hay alguna forma de permitir private herencia private pero prohibiendo public herencia public (probablemente no directamente, pero al menos podemos "simularla")? En este caso, no habrá problemas incluso si usamos una clase con un destructor no virtual, ya que no podemos usar directamente la clase derivada a través de un puntero a la base, por lo que deberíamos estar bien.

Estoy pensando en un código como este:

class Base /*final*/ {}; // making it final prohibits both private and public inheritance class PrivateDerived: private Base{}; // this should work class PublicDerived: public Base{}; // this shouldn''t int main() { PrivateDerived prvd; PublicDerived pubd; // this should not compile // Base* pBase = new PrivateDerived; // doesn''t work, so we are ok }


¡Interesante pregunta! Si no te importa renunciar a la trivialidad del destructor, creo que lo siguiente hace el trabajo:

#include <type_traits> template <typename T> class Base { protected: ~Base() { static_assert(!std::is_convertible<T*,Base*>::value, "Invalid use of public inheritance."); } }; class Derived : public Base<Derived> { }; int main() { Derived d; }

El código anterior no se compila: el static_assert porque Derived* es convertible a Base<Derived>* . Sin embargo, si cambia la herencia a protected o private , el código se compila.

Desafortunadamente los usuarios todavía pueden dispararse en el pie

class Bad : public Base<Derived> { };


No estoy seguro si esto es lo que está buscando o si esto lo ayudará en su caso. Sin embargo demostraré un comportamiento polimórfico.

Constructor protegido clase abstracta

class BaseProtected { // ----- Member Variable Section ----- public: // There Shouldn''t Be Public Variables In A Base Class Unless // That Is The Behavior You Are Looking For - Keep In Mind // Every Inherited Class & Outside Class Can Change Them. protected: // Member Variables Here To Be Shared With Each Derived Class private: // Member Variables Here To Be Used By Base Class Only // ----- Member Function Section ----- public: virtual ~BaseProtected(); // Virtual Destructor void somefunc() const; // Common Function Between All Derived Class virtual void allDerivedMustImplement() const; = 0 // Purely Virtual protected: // Default Constructor - Can Not Declare An Instance Of Base Class BaseProtected(); // Abstract Class // Protected Functions Shared Between Classes // Protected Functions That Are Purely Virtual If Needed private: // Private Functions Used By Base Class Only }; // BaseProtected

Clase Derivada Con Posible Herencia

class DerivedWithPossibleInheritance : public BaseProtected { // ----- Member Variable Section ----- public: // Public Member If Giving Free Access protected: // Protected Members If Being Inherited From private: // Private Members Unique To This Derived Class // ----- Member Function Section ----- public: DerivedWithPossibleInheritance(); // Default Constructor virtual ~DerivedWithPossibleInheritance(); // Virtual Destructor void uniqueFunctionForThisClass() const; void allDerivedMustImplement() const override; private: // Private Functions Unique To This Class }; // DerivedWithPossibleInheritance

Clase derivada que no puede ser heredada de

class DerivedClassCanNotBeInheritedFrom sealed : public BaseProtected { // ----- Member Variable Section ----- public: // Public Members Variables protected: // Should Not Have Member Variables Here For This Class Can Not Be Inherited from private: // Private Members Variables // ----- Member Function Section ------ public: DerivedClassCanNotBeInheritedFrom(); // Default Constructor virtual ~DerivedClassCanNotBeInheritedFrom(); // Default Virtual Destructor void anotherUniqueFunctionForThisClass() const; void allDerivedMustImplement() const override; protected: // There Should Not Be Any Functions Here This Can Not Be Inherited From private: // Private Member Functions Here }; // DerivedClassCanNotBeInheritedFrom

Lo que he demostrado aquí es la palabra clave sellada cuando se trabaja con herencia y polimorfismo. Si no desea que se derive su clase, utilice la palabra clave sellada.

En cuanto a la declaración de cualquier clase base, una clase independiente o una clase de singleton que tenga un Constructor privado, se necesita el uso de la palabra clave friend. Hay muchos tipos de implementaciones con las que se puede involucrar aquí para mostrarlas, pero el concepto de evitar que una clase sea heredada es el mismo. Personalmente no he usado la palabra clave final, pero he usado la palabra clave sellada y funciona muy bien.

No he utilizado la herencia de clases que no sean públicas. Entonces, responder a sus preguntas en términos de herencia protegida o privada no es algo con lo que esté realmente familiarizado. Pero tal vez el uso de la palabra clave sellada pueda ayudarlo.