method c++ inheritance final virtual-inheritance

method - clase final en c++



c++ override virtual method (7)

class Temp { private: ~Temp() {} friend class Final; }; class Final : virtual public Temp { public: void fun() { cout<<"In base"; } }; class Derived : public Final { }; void main() { Derived obj; obj.fun(); }

El código anterior intenta alcanzar una clase no heredable (final). Pero usando el código anterior, el objeto de derivada aún se puede crear, ¿por qué?

La funcionalidad deseada solo se logra si Ctor se hace privada, mi pregunta es ¿por qué no se puede lograr en el caso de dtor privado?


La clase derivada no llama al destructor privado de la clase base, por lo tanto, no necesita visibilidad.

Haga que sus constructores sean privados y solo proporcione una función de generador estático.


Bueno, para este programa (dele provecho de ejemplos correctos y compilables)

#include <iostream> class Temp { private: ~Temp() {} friend class Final; }; class Final : virtual public Temp { public: void fun() { std::cout<<"In base"; } }; class Derived : public Final {}; int main() { Derived obj; obj.fun(); }

Comeau en línea dice

Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2 Copyright 1988-2008 Comeau Computing. All rights reserved. MODE:strict errors C++ C++0x_extensions "ComeauTest.c", line 16: error: "Temp::~Temp()" (declared at line 6) is inaccessible class Derived : public Final { ^ detected during implicit generation of "Derived::Derived()" at line 21 "ComeauTest.c", line 16: error: "Temp::~Temp()" (declared at line 6) is inaccessible class Derived : public Final { ^ detected during implicit generation of "Derived::~Derived()" at line 21 2 errors detected in the compilation of "ComeauTest.c".

Dado que, en caso de duda, siempre confío en como (solo he encontrado un error en él, pero muchos en otros compiladores), supongo que VC9 (que acepta el código) tiene un error. (Desde ese void main() supongo que usas VC también).


Tenga en cuenta que existen clases no heredables en C ++ 11 utilizando la palabra clave final , especificada antes de la lista de herencia : base1, base2, ..., baseN o antes de la apertura { si la clase hereda de la nada:

class Final final { }; class Derived : public Final { }; // ERROR

Con un poco de magia macro y un poco de esfuerzo de detección de compilador esto puede ser abstraído para funcionar o, en el peor, no hacer nada, en todos los compiladores.


Patrón de plantilla curiosamente recurrente. Usa herencia privada

template< typename T > class Final { protected: Final() {} Final( Final const& ) {} }; class X : private virtual Final<X> { // whatever I want to do };

y debería encontrar que es imposible derivar algo de X porque la herencia virtual significa que la clase más derivada debe construir la clase base, pero no tendrá acceso a ella.

(No he probado este código).


Y, por supuesto, la forma correcta de hacerlo hoy es usar la palabra clave final . Por ejemplo:

class Foo final { public: Foo() {} ~Foo() {} void bar() { // ... } };


Modifiqué el código original publicado y verifiqué este código en g ++:

class Temp { private: Temp() { cout << "In Temp Class ctor" << endl; } ~Temp() {} friend class Final; }; class Final : virtual public Temp { public: void fun() { cout<<"In base"; } }; class Derived : public Final { }; int main() { Derived obj; obj.fun(); return 0; }

Resultado: $ g ++ one.cpp -o one -lm -pthread -lgmpxx -kgmp -lreadline 2> & 1

one.cpp: en el constructor ''Derived :: Derived ()'': one.cpp: 8: 9: error: ''Temp :: Temp ()'' es privado Temp () {

one.cpp: 25: 11: error: dentro de esta clase de contexto Derivado: público Final

one.cpp: 11: 9: error: ''Temp :: ~ Temp ()'' es privado ~ Temp () {}

one.cpp: 25: 11: error: dentro de esta clase de contexto Derivado: público Final

one.cpp: 11: 9: error: ''Temp :: ~ Temp ()'' es privado ~ Temp () {}

Nota: Es una buena práctica no usar el vacío con ''principal''.

Gracias,


Las preguntas frecuentes de C ++ describen diferentes formas de lograr esto, pero a partir de su pregunta, supongo que ya las ha leído. ;-)

(Además, main siempre debe devolver int , nunca void ).