2011-01-26 9 views
5

PREGUNTA 1)constructor de C++ Base llamando con el parámetro que será construido en el constructor derivado

class Base { 
    Base(std::string name); 

    virtual std::string generateName(); 
} 

class Derived : Base { 
    Derived(); 

    virtual std::string generateName(); 
} 

aquí viene la pregunta: ¿

qué método será llamado en generateName()?

Derived :: Derived : Base(generateName()) { 
    //what method will be called on generateName() ? 
} 

PREGUNTA 2)

cómo debo hacerlo? si el constructor predeterminado debe aceptar un parámetro, pero necesito generar ese parámetro en el constructor Derivado?

Respuesta

8

Primero, la solución: utilice una función de miembro estático o una función de no miembro.

En cuanto al comportamiento, se llamará Derived::generateName(). La frase larga en el estándar de C++ que define este comportamiento dice (C++ 03 12,7/3):

Cuando una función virtual se llama directa o indirectamente de un constructor (que incluye desde la mem-inicializador para un conjunto de datos miembro) o de un destructor, y el objeto al que se aplica la llamada es el objeto en construcción o destrucción, la función llamada es la definida en el constructor propia clase del destructor o en una de sus bases, pero no una función que anula en una clase derivada de la clase del constructor o del destructor, o anulándola en una de las otras clases base del objeto más derivado.

Debido a que el constructor está ejecutando en el momento de la llamada virtual es el Derived constructor, Derived::generateName() se llama.

Una respuesta eliminada con razón se refiere a un artículo de Scott Meyers que recomienda "Never Call Virtual Functions during Construction or Destruction." Las reglas para lo que se llama a overrider son complejas y difíciles de recordar.

+3

Esto sería cierto si 'generateName()' se llama desde * inside * 'Base :: Base'. Pero aquí, lo llamamos en la lista de inicializadores, antes de ingresar a 'Base :: Base'. ¿Esto sigue siendo cierto? –

+0

Ah, has actualizado tu respuesta. Esto se siente ahora, así que +1. –

+1

@Oli: No. Me equivoqué y he corregido la respuesta después de investigar el problema y ejecutar algunas pruebas. De hecho, estoy algo sorprendido por el comportamiento especificado. Me parece mal ;-) (Rompe el modelo que generalmente he usado para razonar sobre las llamadas a funciones virtuales durante la construcción y ahora tengo que volver y encontrar todas las respuestas en las que describí mal el proceso ... .) Gracias por cuestionar la respuesta original. –

1

tomar dos ...

lo hice una carrera con llamadas a generateName() en el inicializador de clase base y los dos constructores. La salida me dejó nonplussed:

Derived (called from Derived's Base initializer) 
Base (called from Base ctor) 
Derived (called from Derived ctor) 

nunca imaginé que una clase podría transformarse de ser un derivado de una base, a continuación, de nuevo a un derivado de una secuencia de construcción individual. Tu aprendes algo nuevo cada dia.

Cuestiones relacionadas