C++/ Restringir la instancia de clase, qué otras clases se heredan de ella

Quiero hacer una clase en C++, que otras clases heredan de ella. Pero quiero asegurarme de que nadie pueda crear una instancia de esta clase.

Sentido:

class Animal{
public:
virtual ~Animal() {}
};

class Fish: public Animal{
};

Quiero asegurarme de que:

Fish* fish = new Fish();

sería posible, pero

Animal* ana = new Animal();

no lo haría.

¿Cómo puedo hacerlo?

preguntado el 03 de mayo de 12 a las 13:05

Nota: Fish fish; también es posible, no vayas a usar new En todas partes ;) -

4 Respuestas

La solución más sencilla es hacer AnimalEl constructor está protegido:

Class Animal{
protected:
    Animal() {}
public:
    virtual ~Animal() {}
};

Dado que C++ no proporciona soporte explícito para clases abstractas, pero puede agregar funciones virtuales puras a su clase para obtener un efecto similar. Si no tiene una función virtual adecuada que le gustaría hacer puramente virtual, un idioma común es hacer que su destructor sea puramente virtual y luego proporcionar una implementación fuera del encabezado.

Class Animal{
protected:
    Animal() {}
public:
    virtual ~Animal() = 0;
};

Animal::~Animal() {
    // destructor code
}

contestado el 03 de mayo de 12 a las 13:05

10.4 es una sección completa sobre clases abstractas, diría que su soporte es bastante explícito, a menos que explícito solo signifique tener palabras clave para esas cosas. - PlasmaHH

Olvidó el constructor de copia y hay un problema de corte si no hace también el operador de asignación protected. Las clases abstractas son mejores. - Matthieu M.

@PlasmaHH Por "explícito" quiero decir que no hay forma de hacer que una clase sea abstracta sin agregar una función virtual pura, una forma directa de comunicar el hecho de que su clase es abstracta al compilador, incluso si no necesita funciones virtuales, o ninguna función en absoluto. - Serguéi Kalinichenko

@MatthieuM. No los olvidé, el OP lo hizo :) Por supuesto, la regla de tres todavía se aplica. - Serguéi Kalinichenko

@PlasmaHH: No estoy de acuerdo con la idea de que el polimorfismo requiere un virtual incinerador de basuras. Este es un tema aparte. De hecho, sólo se requiere para el delete en el caso base, que no es tan frecuente como las personas con mentalidad de Java esperan que creamos. Dicho esto, el costo de un virtual destructor es tan poco cuando uno ya tiene otro virtual métodos que es más simple agregarlo desde el principio. - Matthieu M.

El idioma habitual para hacer una clase abstracta es tener un destructor virtual puro:

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

Tenga en cuenta que deberá proporcionar una implementación para el destructor, incluso si está marcado como puro:

A::~A()
{
}

contestado el 03 de mayo de 12 a las 13:05

En la práctica, nunca he visto una clase que necesitara ser abstracta y que no tuviera ya algunas funciones virtuales puras. En cuyo caso, no necesita hacer que el destructor sea puramente virtual (pero debería seguir siendo virtual). - james kanze

@Matthieu M.: No tiene nada que ver con la pereza. No deberías asumir tanto sobre los motivos y el pensamiento de las personas. ¿De verdad crees que todas las respuestas cortas significan que sus proveedores son vagos? Ese es un sesgo horrible de tener. ¿Alguna vez se detuvo y consideró otras posibilidades? Suspiro. - Jason

@ Jason: Ironía. No se trata de que seas perezoso o no, es solo que las frases ingeniosas no son buenas respuestas. Las dos deficiencias inherentes son que no proporcionan mucho para indexar (piense en buscar en Google) y que si el enlace se interrumpe alguna vez... no proporcionan nada. No significa que los enlaces sean malos, significa que son útiles como promover referencia, pero la respuesta debería ser capaz de valerse por sí misma. - Matthieu M.

@Matthieu M.: Ese es un comentario mejor y más reflexivo que acusar implícitamente a las personas de pereza. - Jason

@Jason: Estoy de acuerdo, por eso se publicó el comentario irónico en la respuesta que no podía ser acusado de pereza. después de se había publicado un comentario más elaborado en cada de las respuestas de una sola línea. Pensé que sería suficiente para evitar malentendidos... - Matthieu M.

Que sea un clase abstracta

contestado el 03 de mayo de 12 a las 13:05

Que es una clase abstracta ? ¿Cómo hacerlo abstracto? Cuál es la mejor manera aquí ? Las frases de una sola línea... no valen nada. - Matthieu M.

@MatthieuM. A menos que tengas 78k rep. Entonces tu línea recibe 3 votos a favor :) - jrok

Deje que el OP decida si la respuesta vale la pena o no. Permítale hacer esas preguntas si es necesario. - Jason

La forma antigua es hacer que el constructor de Animal esté protegido.

La forma de C++11 es marcar el constructor como eliminado.

contestado el 03 de mayo de 12 a las 14:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.