Pregunta

¿Por qué C++ no tiene un constructor virtual?

No hay solución correcta

Otros consejos

:) Escúchelo de la boca del caballo.

A partir de C ++ de Bjarne Stroustrup estilo y la técnica FAQ ¿Por qué no tenemos constructores virtuales?

  

Una llamada virtual es un mecanismo para realizar su trabajo dada parcial   información. En particular, "virtual" nos permite llamar a una función   conociendo sólo las interfaces y no el tipo exacto del objeto. A   crear un objeto necesita información completa. En particular, se   necesita saber el tipo exacto de lo que se desea crear. Por consiguiente,   una "llamada a un constructor" no puede ser virtual.

La entrada de la FAQ va a dar el código de una manera de lograr este objetivo sin un constructor virtual.

funciones virtuales proporcionan básicamente comportamiento polimórfico. Es decir, cuando se trabaja con un objeto cuyo tipo dinámico es diferente a la estática (tiempo de compilación) tipo con el que se conoce, que proporciona un comportamiento que es apropiado para el real tipo de objeto en lugar de el tipo estático del objeto.

Ahora trata de aplicar ese tipo de comportamiento a un constructor. Cuando se crea un objeto del tipo estático es siempre el mismo que el tipo de objeto real, ya que:

  

Para construir un objeto, un constructor necesita el tipo exacto del objeto que es crear [...] Por otra parte, [...] no se puede tener un puntero a un constructor

(Bjarne Stroustup (P424 El C ++ Programming Language SE))

diferencia de los lenguajes orientados a objetos tales como Smalltalk o Python, en el que el constructor es un método virtual del objeto que representa la clase (lo que significa que no necesita el GoF patrón de fábrica abstracta , como se puede pasar el objeto que representa la clase alrededor en vez de hacer el suyo propio), C ++ es un lenguaje basado en la clase, y no tiene ninguna objetos que representan de las construcciones del lenguaje. La clase no existe como un objeto en tiempo de ejecución, por lo que no se puede llamar a un método virtual en él.

Esto encaja con la filosofía 'no paga por lo que no utiliza', aunque cada gran proyecto de C ++ que he visto ha terminado la aplicación de alguna forma de la fábrica abstracta o la reflexión.

dos razones que se me ocurren:

La razón técnica

El objeto existe sólo después de la orden ends.In constructor para el constructor para ser enviado usando la tabla virtual, tiene que haber un objeto existente con un puntero a la tabla virtual, pero ¿cómo puede existir un puntero a la tabla virtual Si todavía no existe el objeto? :)

razón lógica

Se utiliza la palabra reservada virtual cuando se desea declarar un comportamiento algo polimórfica. Pero no hay nada polimórfico con los constructores, constructores de trabajo en C ++ es simplemente poner un conjunto de datos de objetos en la memoria. Desde tablas virtuales (y polimorfismo en general) son todo sobre el comportamiento polimórfico en lugar de los datos polimórficos, No hay sentido de declarar un constructor virtual.

Lo hacemos, simplemente no es un constructor: -)

struct A {
  virtual ~A() {}
  virtual A * Clone() { return new A; }
};

struct B : public A {
  virtual A * Clone() { return new B; }
};

int main() {

   A * a1 = new B;
   A * a2 = a1->Clone();    // virtual construction
   delete a2;
   delete a1;
}

razones semánticas a un lado, no hay vtable hasta después de que el objeto se construye, haciendo así una designación virtual inútil.

Resumen : el estándar de C ++ podría especificar una notación y el comportamiento de "constructor virtual" s que es bastante intuitiva y no demasiado duro para compiladores de apoyo, pero ¿por qué hacer un cambio estándar para este específicamente cuando el funcionalidad pueden ya es posible realizar limpiamente usando create() / clone() (ver más abajo)? No es casi tan útil como muchos propuesta de otro idioma en la tubería.

discusión

Vamos a postular un mecanismo de "constructor virtual":

Base* p = new Derived(...);
Base* p2 = new p->Base();  // possible syntax???

En lo anterior, la primera línea construye un objeto Derived, por lo tabla de despacho virtual de *p razonablemente puede suministrar un "constructor virtual" para su uso en la segunda línea. (Decenas de respuestas en esta página, indicando el "el objeto no existe todavía la construcción de manera virtual es imposible" son innecesariamente centró miope en el objeto a ser construido.)

La segunda línea postula la new p->Base() notación para solicitar la asignación y el defecto construcción dinámica de otro objeto Derived.

Notas:

  • el compilador debe orquestar la asignación de memoria antes de llamar al constructor - constructores normalmente apoyan (informalmente "pila") asignación automática, estática (por alcance / espacio de nombres global y los objetos de clase / función-static), y dinámico (informalmente "montón") cuando se utiliza new

    • el tamaño del objeto a ser construido por p->Base() no puede generalmente ser conocido en tiempo de compilación, de modo asignación dinámica es el único enfoque que tiene sentido

  • para la asignación dinámica que debe devolver un puntero de modo que la memoria puede ser deleted más tarde.

  • la notación postulado explícitamente enumera new hacer hincapié en la asignación dinámica y el tipo de resultado puntero.

El compilador tendría que:

  • Para saber cuánta memoria Derived necesario, ya sea llamando a una función virtual sizeof implícita o tener dicha información disponible a través de RTTI
  • operator new(size_t) llamada a asignar memoria
  • invocar Derived() con new colocación.

o

  • crear una entrada vtable extra para una función que combina la asignación dinámica y la construcción

Por lo tanto - no parece insalvable para especificar e implementar constructores virtuales, pero la pregunta del millón es: ¿cómo sería mejor que lo que es posible el uso de las características existentes ++ lenguaje C ...? En lo personal, No veo ninguna ventaja sobre la solución a continuación.


`clone ()` y `crear ()`

El C ++ FAQ documenta un "constructor virtual" modismo , conteniendo métodos virtual create() y clone() a default-constructo o copia-construir un nuevo objeto asignado dinámicamente:

class Shape {
  public:
    virtual ~Shape() { } // A virtual destructor
    virtual void draw() = 0; // A pure virtual function
    virtual void move() = 0;
    // ...
    virtual Shape* clone() const = 0; // Uses the copy constructor
    virtual Shape* create() const = 0; // Uses the default constructor
};
class Circle : public Shape {
  public:
    Circle* clone() const; // Covariant Return Types; see below
    Circle* create() const; // Covariant Return Types; see below
    // ...
};
Circle* Circle::clone() const { return new Circle(*this); }
Circle* Circle::create() const { return new Circle(); }

También es posible cambiar o create() sobrecarga para aceptar los argumentos, aunque para que coincida con la firma función virtual la base de clase / de interfaz, argumentos a las anulaciones deben coincidir exactamente con una de las sobrecargas de la clase base. Wisconsinº estas instalaciones proporcionados por el usuario explícitos, es fácil añadir la explotación forestal, la instrumentación, alterar la asignación de memoria, etc ..

Puede encontrar un ejemplo y la razón técnica por la que no está permitido en la respuesta de @stefan.Ahora, según yo, una respuesta lógica a esta pregunta es:

El uso principal de la palabra clave virtual es habilitar el comportamiento polimórfico cuando no sabemos a qué tipo de objeto apuntará el puntero de la clase base.

Pero piense que esta es una forma más primitiva: para usar la funcionalidad virtual necesitará un puntero.¿Y qué requiere un puntero?¡Un objeto para señalar!(considerando caso para la correcta ejecución del programa)

Entonces, básicamente requerimos un objeto que ya exista en algún lugar de la memoria (no nos preocupa cómo se asignó la memoria, puede ser en tiempo de compilación o en tiempo de ejecución) para que nuestro puntero pueda apuntar correctamente a ese objeto.

Ahora, piense en la situación en el momento en que al objeto de la clase a señalar se le asigna algo de memoria -> ¡Su constructor será llamado automáticamente en esa instancia!

Entonces podemos ver que en realidad no necesitamos preocuparnos de que el constructor sea virtual, porque en cualquiera de los casos en los que desee utilizar un comportamiento polimórfico, nuestro constructor ya se habría ejecutado, ¡lo que dejaría nuestro objeto listo para su uso!

A pesar de que el concepto de constructores virtuales no encajan bien ya que el tipo de objeto es requisito previo para la creación de objetos, no es completamente gobernado.

patrón de diseño 'método de fábrica' del Gobierno de Francia hace uso del 'concepto' del constructor virtual, que es Handly en ciertas situaciones de diseño.

funciones virtuales en C ++ son una implementación de polimorfismo en tiempo de ejecución, y que van a hacer la función primordial. Generalmente la palabra clave virtual se utiliza en C ++ cuando se necesita un comportamiento dinámico. Se trabajará solamente cuando existe objeto. Mientras que los constructores se utilizan para crear los objetos. Constructores serán llamados en el momento de la creación de objetos.

Así que si crea el constructor como virtual, según la definición de palabras clave virtual, se debe tener objeto existente de usar, pero constructor se utiliza para crear el objeto, por lo que este caso nunca existirá. Lo que no debe utilizar el constructor como virtual.

Por lo tanto, si tratamos de declarar compilador constructor virtual de lanzar un error:

  

Los constructores no pueden ser declarados virtuales

Cuando la gente pregunta una pregunta como ésta, me gusta pensar que a mí mismo "¿Qué pasaría si esto fuera realmente posible?" No se sabe muy bien lo que esto significaría, pero supongo que tendría algo que ver con la posibilidad de sustituir la implementación del constructor basado en el tipo dinámico del objeto que está siendo creado.

Veo una serie de posibles problemas con esto. Por un lado, la clase derivada no será totalmente construido en el momento del constructor virtual se llama, por lo que hay problemas potenciales con la aplicación.

En segundo lugar, lo que sucedería en el caso de la herencia múltiple? Su constructor virtual sería llamado varias veces, presumiblemente, A continuación, tendría que tener alguna manera de saber cuál era llamado.

En tercer lugar, en términos generales en el momento de la construcción, el objeto no tiene la mesa virtual completamente construido, esto significa que requeriría un gran cambio en la especificación del lenguaje para permitir el hecho de que el tipo dinámico del objeto sería conocido en el momento de la construcción. Esto permitiría al constructor de la clase base para llamar tal vez otras funciones virtuales en el momento de la construcción, con un tipo de clase dinámica no totalmente construida.

Por último, como alguien ha señalado se puede implementar un tipo de constructor virtual usando "init" funciones de tipo estático "crear" o que básicamente hacen lo mismo como constructor virtual sería hacer.

funciones virtuales se utilizan para invocar funciones basadas en el tipo de objeto apuntado por el puntero, y no el tipo de puntero en sí. Pero un constructor no es "invocado". Se llama sólo una vez cuando se declara un objeto. Por lo tanto, un constructor no puede hacerse virtual en C ++.

No debe llamar a la función virtual dentro del constructor tampoco. Ver: http://www.artima.com/cppsource/nevercall.html

Además no estoy seguro de que usted realmente necesita un constructor virtual. Se puede lograr una construcción polimórfica sin ella:. Puede escribir una función que va a construir su objeto de acuerdo con los parámetros necesarios

A-mesa virtual (vtable) se realiza para cada clase tiene una o más "virtuales-funciones. Siempre que se crea un objeto de dicha clase, que contiene un 'virtual triple', que apunta a la base de vtable correspondiente. Siempre que hay una llamada a una función virtual, la viable se utiliza para resolver a la dirección de la función.     Constructor no puede ser virtual, porque cuando se ejecuta el constructor de una clase que no hay vtable en la memoria, significa que no hay puntero virtual definido todavía. Por lo tanto el constructor siempre debe ser no virtual.

No puedo simplemente decir que como .. No podemos heredar constructores. Así que no hay punto de declararlos virtual debido a la virtual proporciona polimorfismo.

El mecanismo virtual sólo funciona cuando se tiene un puntero de clase basada en un objeto de clase derivada. La construcción tiene sus propias reglas para la convocatoria de constructores de clase base, básicamente clase base a deriva. ¿Cómo podía un constructor virtual de ser útil o llamada? No sé qué otras lenguas hacer, pero no puedo ver cómo un constructor virtual podría ser útil o incluso implementado. necesidades de la construcción que han tenido lugar para el mecanismo virtual que tenga sentido y la construcción también tiene que haber tenido lugar a las estructuras vtable que se han creado, que ofrece la mecánica del comportamiento polimórfico.

Hay una razón muy básica:. Los constructores son funciones con eficacia estáticos, y en C ++ ninguna función estática puede ser virtual

Si usted tiene mucha experiencia con C ++, ya sabes todo acerca de la diferencia entre las funciones estáticas y miembros. funciones estáticas están asociados con la clase, no los objetos (instancias), por lo que no ven un puntero "this". Sólo las funciones miembro pueden ser virtuales, debido a que el vtable- la tabla oculta de los punteros de función que hace 'virtual' de obra es en realidad un miembro de datos de cada objeto.

Ahora, lo que es el trabajo del constructor? Es en el nombre- un constructor "T" T inicializa los objetos a medida que se asignan. Esto impide automáticamente que sea una función miembro! Un objeto tiene que existir antes de que tenga un puntero "this" y por lo tanto un vtable. Eso significa que incluso si los constructores tratado de lenguaje como funciones ordinarias (no, por razones relacionadas no voy a entrar en), que tendrían que ser funciones miembro estáticas.

Una gran manera de ver esto es mirar el patrón "de fábrica", en especial las funciones de fábrica. Ellos hacen lo que está buscando, y usted notará que si la clase T tiene un método de fábrica, siempre es estática. Tiene que ser.

constructor virtual de C ++ no es ejemplo possible.For no se puede marcar un constructor como virtual.Try este código

#include<iostream.h>
using namespace std;
class aClass
{
    public:
        virtual aClass()
        {   
        }  
};
int main()
{
    aClass a; 
}

Esto causa un código error.This está tratando de declarar un constructor como virtual. Ahora vamos a tratar de entender por qué usamos la palabra clave virtual. palabra clave virtual se utiliza para proporcionar polimorfismo de tiempo de ejecución. Por ejemplo probar este código.

#include<iostream.h>
using namespace std;
class aClass
{
    public:
        aClass()
        {
            cout<<"aClass contructor\n";
        }
        ~aClass()
        {
            cout<<"aClass destructor\n";
        }

};
class anotherClass:public aClass
{

    public:
        anotherClass()
        {
            cout<<"anotherClass Constructor\n";
        }
        ~anotherClass()
        {
            cout<<"anotherClass destructor\n";
        }

};
int main()
{
    aClass* a;
    a=new anotherClass;
    delete a;   
    getchar(); 
}

En a=new anotherClass; principal asigna una memoria para anotherClass en un a puntero declarado como tipo de aClass.This hace que tanto el constructor (En aClass y anotherClass) para llamar automatically.So que no necesitamos para marcar constructor como cuando un virtual.Because objeto se crea que debe seguir la cadena de la creación (es decir, primero la base y luego las clases derivadas). Pero cuando tratamos de eliminar una delete a; que causa a llamar sólo la base destructor.So tenemos que manejar el destructor usando la palabra clave virtual. constructor Así virtual no es posible, pero es destructor virtual .¡AGRADECE

Si usted piensa con lógica acerca de cómo los constructores de trabajo y cuál es el significado / uso de una función virtual se encuentra en C ++ y luego se dará cuenta de que un constructor virtual no tendría sentido en C ++. Declarando algo virtual en C ++ significa que puede ser anulado por una subclase de la clase actual, sin embargo, se crea el constructor se llama cuando el opuesto, en ese momento no se puede estar creando una subclase de la clase, debe ser la creación de la clase por lo que nunca podría ser cualquier necesidad de declarar un constructor virtual.

Y otra razón es, los constructores tienen el mismo nombre que el nombre de clase y si declaramos constructor como virtual, entonces deben ser redefinido en su clase derivada con el mismo nombre, pero no se puede tener el mismo nombre de dos clases. Por lo que no es posible tener un constructor virtual.

  1. Cuando se invoca un constructor, aunque no hay un objeto creado hasta ese momento, todavía sabemos el tipo de objeto que se va a se puede crear porque el constructor específico de la clase a la cual pertenece el objeto ya ha sido llamado.

    palabra clave Virtual asociado con una función significa que el función de un tipo de objeto particular, va a se ser llamado.

    Por lo tanto, mi pensamiento dice que no hay necesidad de hacer que el constructor virtual, porque ya el constructor deseado que tiene por objeto que va a ser creado ha sido invocado y haciendo constructor virtual es sólo una cosa que hacer redundante porque el objeto- constructor específico ya ha sido invocada y esto es igual que llamar a función específica de clase que se logra a través de la palabra clave virtual.

    Aunque la aplicación interna no permitirá constructor virtual para VPTR y motivos relacionados vtable.


  1. Otra razón es que C ++ es un lenguaje de tipos estáticos y necesitamos saber el tipo de una variable en tiempo de compilación.

    El compilador debe tener en cuenta el tipo de clase para crear el objeto. El tipo de objeto que se ha creado es una decisión en tiempo de compilación.

    Si hacemos el constructor virtual de entonces significa que no es necesario conocer el tipo del objeto en tiempo de compilación (que es lo que proporciona una función virtual. No necesitamos saber el objeto real y sólo tiene la puntero de base para señalar un objeto real llamar a funciones virtuales del objeto puntiagudo sin conocer el tipo de objeto) y si no sabemos el tipo de objeto en tiempo de compilación, entonces es en contra de las lenguas tipos estáticos. Y por lo tanto, el polimorfismo en tiempo de ejecución no se puede lograr.

    Por lo tanto, Constructor no se llama sin conocer el tipo del objeto en tiempo de compilación. Y así, la idea de hacer un constructor virtual falla.

El Vpointer se crea en el momento de la creación de objetos. vpointer costumbre existe antes de la creación de objetos. lo que no hay punto de hacer que el constructor como virtual.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top