Llamando a un método en el constructor

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

Ahora considera el siguiente código

class A { public: A() { f(); } void f() { cout << "hello, world"; } }; int main() { A a; } 

Ahora, por lo que dice Herb, no podemos decir que, dado que A no está completamente construido dentro de su constructor, llamar a f () dentro del constructor no es válido ya que la ptr “this” no está lista todavía.

Aún así, de hecho hay un “esto” válido dentro del constructor y se llama a f ().

No creo que Herb esté diciendo algo incorrecto … pero supongo que lo estoy interpretando incorrectamente … ¿Puede alguien explicarme qué es exactamente eso?

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

-¿Cuándo comienza la vida de un objeto? Cuando su constructor se completa con éxito y vuelve normalmente . Es decir, el control llega al final del cuerpo del constructor o una statement de retorno anterior.

-¿Cuándo termina la vida de un objeto? Cuando comienza su destructor. Es decir, el control llega al principio del cuerpo destructor. El punto importante aquí es que el estado del objeto antes de que comience su vida útil es exactamente el mismo que después de que finaliza su vida útil: no hay objeto, punto . 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. 

Ahora, por lo que dice Herb, no podemos decir que, dado que A no está completamente construido dentro de su constructor, llamar a f () dentro del constructor no es válido ya que la ptr “this” no está lista todavía.

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

Si f() no es una función virtual, no hay ningún daño en llamarla desde el (los) constructor (es) siempre que sepa qué hace exactamente f() . Los progtwigdores usualmente llaman métodos de clase como initialize() desde el (los) constructor (es).

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

Cuando el flujo del progtwig ingresa a su constructor, la memoria del objeto se ha asignado y el puntero es válido.

Lo que significa Herb, es que el estado del objeto puede no haberse inicializado por completo. En particular, si está construyendo una clase derivada de A , entonces no se habrá llamado al constructor de esa clase mientras aún se encuentre 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.

La implicación de que el tiempo de vida aún no ha comenzado es principalmente que, si el constructor lanza una excepción, el destructor no se ejecutará.

Nota: hubiera sido más fácil con el artículo exacto, para que pudiéramos tener algún contexto

Las consideraciones de por vida son en realidad bastante complicadas.

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

  • externo: es decir, el usuario de un objeto
  • interno: es decir, cuando escribes constructores y destructores (notablemente)

Desde el punto de vista externo, la vida útil de un objeto:

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

Significa que si intentas acceder a un objeto en construcción media o destrucción media, suceden cosas malas ™ . Esto es mayormente relevante para progtwigs de subprocesos múltiples, pero puede suceder si pasas punteros a tu objeto a clases básicas … lo que lleva a …

… el punto de vista interno. Es más complicado. Una cosa de la que está seguro es que la memoria requerida ha sido asignada, sin embargo, es posible que algunas partes de los objetos aún no se hayan inicializado completamente (después de todo, la 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 (deben evitarse las llamadas virtuales).
  • si es una clase base, el objeto derivado aún no se ha inicializado (por lo tanto, la restricción en las llamadas virtuales)

Cuidado con las variables miembro que aún no están inicializadas. Tenga cuidado con las funciones virtuales: la función a la que llama podría 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 a métodos del constructor. Especialmente la memoria para el objeto ya ha sido asignada.