2011-06-07 9 views
14

Además de tener una función virtual pura, ¿hay alguna manera de evitar una instanciación de una clase base abstracta?C++: ¿alguna forma de evitar la creación de instancias de una clase base abstracta?

Puedo hacer esto:

class BaseFoo 
{ 
    virtual void blah() = 0; 
}; 

class Foo : public BaseFoo 
{ 
    virtual void blah() {} 
}; 

pero me gustaría evitar una vtable. (Según my other question about virtual destructors)

Microsoft ATL tiene ATL_NO_VTABLE de lograr esto (o por lo menos creo que eso es lo que hace ...)

+2

¿Por qué exactamente quieres evitar un vtable? (Y, si nunca va a utilizar el hecho de que el método es virtual, ¿por qué está molestando con una clase base?) \ –

Respuesta

34

Una muy manera obvia es declarar un constructor protegido, y declarar constructores públicos en las clases derivadas no abstractas.

Esto, por supuesto, desplaza la carga de la correlación a las clases derivadas, pero al menos la clase base está protegida.

+0

Agradable. Pero tal vez no sea "realmente obvio" ;-) – Johnsyweb

+3

¡Bien, obvio en comparación con los hacks de plantillas locos que esperaba que la gente publicara! – Blindy

+0

Bien, obvio para ti :-) – Johnsyweb

-4

Si comete un constructor protegida tal como se aconseja aquí, a continuación, cuando su clase derivada se construye obtendrá un error similar a "no puede miembro privado de acceso declarado en la clase", con otra información específica para sus clases.

Si tiene métodos virtuales puros en su clase base, entonces el problema no es que esos sean instanciados (y ciertamente no es que se crean instancias de métodos no abstractos), pero el problema ocurre en tiempo de destrucción cuando el compilador puede no inferir qué posee tu clase derivada. ¡Eso, o has instanciado cosas sin un dueño! (ruh roh rhaggy)

Declare un destructor virtual puro para su clase base y luego impleméntelo externamente. Además, nunca, nunca haga que un constructor sea privado (edit: a menos que se garantice que solo se use internamente, como la construcción automática del siguiente nodo en una lista vinculada). Lo más cerca que va siempre quiero (editar: lo contrario) es un constructor explícito (pero ese es otro tema).

ediciones: Es posible que haya encontrado la respuesta, pero todavía no puedo escribir hoy.

// example.h 

class A 
{ 

    A () { } 
    virtual ~A () = 0; 
}; 

class B : public A 
{ 
    B () { } 
    ~B () { } 
}; 

// example.cpp 
#include "example.h" 

A::~A () { } 
+1

'Si hace un constructor ** protegido ** ... obtiene un error ... "no puede acceder ** miembro ** privado ....'? Si el constructor está' protegido' y no 'privado' usted ganó Obtiene cualquier error en la clase derivada que le informa sobre el acceso a un miembro privado, ya que simplemente no es privado. – Pixelchemist

+0

Toda esta "respuesta" (más un comentario sobre el otro, respuestas reales) es incorrecta. – Blindy

Cuestiones relacionadas