virtuales method funciones example español c++ class inheritance derived-class sealed

c++ - method - sealed class c# español



¿Cómo se define la clase sellada en C++? (6)

Cómo detener la clase para que sea heredada por otra clase.


Solución C ++ 11

En C ++ 11, puede sellar una clase utilizando final palabra clave final en la definición como:

class A final //note final keyword is used after the class name { //... }; class B : public A //error - because class A is marked final (sealed). { // so A cannot be derived from. //... };

Para conocer los otros usos de final, vea mi respuesta aquí:

Solución C ++ 03

Código de Bjarne Stroustrup : ¿Puedo detener a las personas derivadas de mi clase?

class Usable; class Usable_lock { friend class Usable; private: Usable_lock() {} Usable_lock(const Usable_lock&) {} }; class Usable : public virtual Usable_lock { public: Usable(); Usable(char*); }; Usable a; class DD : public Usable { }; DD dd; // error: DD::DD() cannot access // Usable_lock::Usable_lock(): private member

Generic_lock

Así que podemos hacer uso de la plantilla para hacer que Usable_lock suficientemente genérico como para sellar cualquier clase:

template<class T> class Generic_lock { friend T; Generic_lock() {} //private Generic_lock(const Generic_lock&) {} //private }; class Usable : public virtual Generic_lock<Usable> { public: Usable() {} }; Usable a; //Okay class DD : public Usable { }; DD dd; //Not okay!


Basado en las preguntas frecuentes de http://www.stroustrup.com/bs_faq2.html#no-derivation Bjarne Stroustrup con pequeñas modificaciones sin el uso de palabras clave de amigos:

// SEALED CLASS DEFINITIONS class Usable_lock { protected: Usable_lock() {} Usable_lock(const Usable_lock&) {} }; #define sealed_class private virtual Usable_lock // SEALED CLASS USAGE EXMAPLES class UsableLast : sealed_class { public: UsableLast(){} UsableLast(char*){} }; class DD : public UsableLast {}; // TEST CODE template <class T> T createInstance() { return T(); } int main() { createInstance<UsableLast>(); // createInstance<DD>(); return 0; }


C ++ 11 agrega la capacidad de evitar heredar de las clases o simplemente prevenir los métodos de anulación en las clases derivadas. Esto se hace con el identificador especial final . Por ejemplo:

class Base final { }; class Derived1 : Base { }; // ill-formed because the class Base has been marked final

o

class Base { virtual void f() final; }; class Derived : Base { void f(); // ill-formed because the virtual function Base::f has been marked final

Tenga en cuenta que final no es una palabra clave de idioma. Es técnicamente un identificador; solo adquiere un significado especial cuando se usa en esos contextos específicos. En cualquier otra ubicación, puede ser un identificador válido.


El siguiente código muestra cómo definir una clase sellada en C ++ / CLI.

class A sealed { //here goes the class code }; class B : public A { };

Ahora B: no puede heredar de A ya que ha sido declarado como ''sellado''. También se puede encontrar una explicación detallada sobre la palabra clave sellada aquí http://msdn.microsoft.com/en-us/library/0w2w91tf.aspx

Actualización: Se agregó C ++ / CLI, también otras respuestas han mostrado la última forma en C ++ 11 de lograr lo mismo con final palabra clave final .


Hay dos formas, la simple barata y la correcta. Las dos respuestas de @Naveen y @Nawaz se refieren al correcto, que requiere la creación manual de una clase de sellador para cada clase que realmente desea sellar.

La forma no infalible, que se utiliza en las bibliotecas de adobe está utilizando una clase de plantilla para eso. El problema es que no puede declarar el argumento de la plantilla como un amigo, y eso significa que tendrá que pasar de la protected private a la protected menos segura:

template <typename T> class sealer { protected: sealer() {} }; class sealed : virtual sealer<sealed> {};

Y puede automatizarlo con una macro (no recuerdo el sabor exacto de la macro en el código de Adobe):

#define seal( x ) virtual sealer<x> class sealed : seal(sealed) {};

Ahora esto atrapará a las personas que equivocadamente intentan heredar sin saber que no deberían:

class derived : sealed {}; int main() { derived d; // sealer<T>::sealer() is protected within this context }

Pero no inhibirá a las personas que realmente desean derivar, ya que pueden obtener acceso al constructor derivando de la plantilla ellos mismos:

class derived : sealed, sealer<sealed> {}; int main() { derived d; };

No estoy seguro de si esto cambiará en C ++ 0x, creo que recuerdo algunas discusiones sobre si una plantilla de clase podría ser amistosa con uno de sus argumentos, pero en una búsqueda superficial del borrador realmente no puedo decirlo. Si eso fue permitido, entonces esta sería una solución genérica bien:

template <typename T> class sealer { sealer() {} friend class T; // Incorrect in C++03 };


No puedes. C ++ no es Java o C #. Y también no tiene sentido, nunca, en mi humilde opinión.