Вызов базового конструктора C ++ с параметром, который будет создан в производном конструкторе - PullRequest
5 голосов
/ 26 января 2011

ВОПРОС 1)

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

    virtual std::string generateName();
}

class Derived : Base {
    Derived();

    virtual std::string generateName();
}

здесь возникает вопрос:

какой метод будет вызываться для generateName ()?

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

ВОПРОС 2)

как мне это сделать? если конструктор по умолчанию должен принимать параметр, но мне нужно сгенерировать этот параметр в конструкторе Derived?

Ответы [ 2 ]

8 голосов
/ 26 января 2011

Во-первых, решение: используйте статическую функцию-член или функцию, не являющуюся членом.

Что касается поведения, будет вызвано Derived::generateName().Длинное предложение в Стандарте C ++, которое определяет это поведение, говорит (C ++ 03 12.7 / 3):

Когда виртуальная функция вызывается прямо или косвенно из конструктора (в том числе из mem-initializer)для элемента данных) или из деструктора, и объект, к которому применяется вызов, является объектом, находящимся в процессе создания или уничтожения, вызываемая функция является той, которая определена в собственном классе конструктора или деструктора или в одной из его баз, но неФункция переопределяет его в классе, производном от класса конструктора или деструктора, или переопределяет его в одном из других базовых классов наиболее производного объекта.

Поскольку конструктор выполняется во время виртуальногоcall является конструктором Derived, вызывается Derived::generateName().

Теперь удаленный ответ справедливо ссылается на статью Скотта Мейерса, в которой рекомендуется «Никогда не вызывать виртуальные функции во время строительства или разрушения». Правила вызова переопределителей сложны и трудны для понимания.помню.

1 голос
/ 26 января 2011

Взять два ...

Я выполнил прогон с вызовами generateName() в инициализаторе базового класса и обоих конструкторах.Вывод оставил меня в замешательстве:

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

Я никогда не думал, что класс может превратиться из производного в базу, а затем обратно в производный в одной последовательности построения.Вы узнаете что-то новое каждый день.

...