2011-02-02 29 views
17

Herb Sutter menciona en uno de sus artículos http://www.gotw.ca que un objeto está construido (tiene existencia válida) solo si el constructor ejecuta complete.ie para ponerlo de una manera cruda, el control pasa más allá de su corchete final.Llamar a un método en Constructor

Ahora consideremos el siguiente código

class A 
{ 
    public: 
    A() 
    { 
     f(); 
    } 

    void f() 
    { 
     cout << "hello, world"; 
    } 

}; 

int main() 
{ 
    A a; 
} 

Ahora de lo que dice Herb, no podemos decir que ya que A no está completamente construido en el interior de su constructor Llamada f() dentro del constructor no es válido como el "presente "ptr aún no está listo.

Todavía hay de hecho un "esto" válido dentro del constructor y se llama a f().

no creo que la hierba está diciendo algo incorrecto ... pero supongo que estoy interpretando de forma incorrecta puede .... algunos me explique qué es exactamente lo que es?

Aquí está el enlace al artículo: http://www.gotw.ca/gotw/066.htm Habla de las excepciones de los constructores. Específicamente aquí está el extracto del mismo en el que se basa mi pregunta:

- ¿Cuándo comienza la vida útil de un objeto? Cuando su constructor finaliza correctamente y devuelve normalmente. Es decir, el control llega al final del cuerpo del constructor o una declaración de devolución anterior.

-Cuando finaliza el tiempo de vida de un objeto? Cuando comienza su destructor. Es decir, el control llega al comienzo del cuerpo del destructor. punto importante aquí es que el estado del objeto antes de que comience su vida útil es exactamente el mismo que después de sus extremos por vida - no hay ningún objeto, periodo. Esta observación nos lleva a la pregunta clave:

Podríamos resumir el modelo de constructor de C++ de la siguiente manera:

Either: 

(a) The constructor returns normally by reaching its end or a return statement, and the object exists. 

Or: 

(b) The constructor exits by emitting an exception, and the object not only does not now exist, but never existed. 

Respuesta

15

Ahora de lo que dice Herb, no podemos decir que, dado que A no es completamente construidos dentro de su constructor f Calling() dentro del constructor es inválida como el "este" ptr no está listo todavía.

Eso es sólo cuando f() es un método de class A o su jerarquía de herencia virtual y se espera que el tiempo de ejecución para la resolución f() de acuerdo con el objeto correcto. En palabras simples, el mecanismo virtual no entra en juego si el método se invoca dentro del constructor.

Si f() no es una función virtual, no hay nada de malo en llamarlo desde el constructor (es) siempre que sepa exactamente qué hace f(). Los programadores usualmente llaman métodos de clase como initialize() desde el constructor (es).

¿Me puede dar el enlace al artículo de la Herb Sutter?

+7

"Parece que no ha leído el artículo Herb Sutter con cuidado." - Un poco duro considerando que no puedes echarle mano al artículo todavía ... – razlebe

+0

@sgreeve: áspero? ¿por qué? – Nawaz

+3

Usted está asumiendo que el OP no leyó el artículo cuidadosamente. Sin ver el artículo, no se sabe si explicaba bien la situación, si es que lo hacía. – razlebe

8

por el flujo de programa de tiempo entra en su constructor, la memoria del objeto ha sido asignado y el puntero this es de hecho válida.

Lo que Herb significa es que el estado del objeto puede no haberse inicializado por completo. En particular, si está construyendo una clase derivada de A, entonces el constructor de esa clase no se habrá invocado mientras usted todavía esté dentro del constructor de A.

Esto es importante si tiene funciones miembro virtuales, ya que cualquier función virtual en la clase derivada no se ejecutará si se llama desde el constructor de A.

0

Tenga cuidado con las variables miembro que aún no se han inicializado. Tenga cuidado con las funciones virtuales: la función a la que llama puede no ser la que espera si la función es virtual y se crea un objeto derivado. Aparte de eso, no veo ningún problema al llamar métodos del constructor. Especialmente la memoria para el objeto ya ha sido asignada.

2

La implicación de la duración no iniciada es principalmente que, si el constructor lanza una excepción, el destructor no se ejecutará.

2

Nota: habría sido más fácil con el artículo exacta, por lo que podríamos tener algún contexto

consideraciones de por vida son en realidad bastante complicado.

Teniendo en cuenta el constructor de un objeto, hay dos puntos diferentes de vista:

  • externo: es decir, el usuario de un objeto
  • interna: es decir, que al escribir constructores y destructores (en particular)

Desde el punto de vista externo, el tiempo de vida de un objeto:

  • comienza una vez que el constructor ha completado con éxito
  • termina cuando el destructor comienza a correr

Esto significa que si se intenta acceder a un objeto mediados de construcción o mediados de destrucción suceden cosas malas (tm). Esto es principalmente relevante para los programas de subprocesos múltiples, pero puede suceder si pasa punteros a su objeto a las clases base ... lo que conduce a ...

... el punto de vista interno. Es más complicado. Una cosa de la que está seguro es que se ha asignado la memoria requerida; sin embargo, algunas partes de los objetos aún no se han inicializado completamente (después de todo, lo está construyendo).

  • En el cuerpo del constructor, puede usar los atributos y las bases de la clase (se inicializan) y las funciones de llamada normalmente (las llamadas virtuales deben evitarse).
  • si se trata de una clase base, el objeto derivado no se ha iniciado todavía (por lo tanto la restricción de llamadas virtuales)
Cuestiones relacionadas