2013-05-05 3 views
1

class diagramМожно ли вызвать виртуальный метод из конструктора абстрактного класса?

В настоящее время у меня есть «много кода», как указано на диаграмме внутри конструктора каждого ребенка. Моя цель - перенести его в конструктор родителя.

+0

Нет, вы не должны вызывать виртуальные методы от конструкторов или деструкторов. – juanchopanza

+0

Возможный дубликат [Вызов виртуальных функций внутри конструкторов] (http://stackoverflow.com/questions/962132/calling-virtual-functions-inside-constructors) – juanchopanza

ответ

10

Можно ли вызвать виртуальный метод из конструктора абстрактного класса?

Технически это возможно, но это не будет работать, как вы ожидаете, так не делает это, потому что виртуальная таблица для производных классов не была построена еще.

Реализация создаваемого класса будет вызываться, когда виртуальная функция вызывается из конструктора, а если виртуальная функция, которую вы вызываете, является чистой, вы получаете неопределенное поведение.

в соответствии с пунктом 10.4/6 C++ 11 Стандарт на:

Функции-члены могут быть вызваны из конструктора (или деструктора) абстрактного класса; влияние виртуального вызова (10.3) на чистую виртуальную функцию прямо или косвенно для создаваемого (или уничтоженного) объекта от такого конструктора (или деструктора) не определено.

+0

Фактически, вызов чистой виртуальной функции является UB независимо от того, чистая функция имеет реализацию. То есть Даже если вы намеренно предоставляете определение для чистой виртуальной функции, вызов ее таким образом, который использует виртуальную диспетчеризацию (т. Е. Не 'classname ::'), все еще вызывает UB просто потому, что функция объявлена ​​чистой. –

+0

@CharlesBailey: Я отредактировал ответ. Я только что узнал, что чистая виртуальная функция может иметь реализацию :) Спасибо за исправление меня –

+0

@AndyProwl Эффективный C++ 3rd Ed. В элементе 34 есть хорошая работа по реализации чистых виртуальных функций, но также отмечается, что: «Помимо того, что вы помогаете произвести впечатление на своих коллег-программистов на коктейльной вечеринке, знание этой функции, как правило, ограничено». Их основное назначение - предоставить нечистые виртуальные функции с реализацией по умолчанию, и вы должны называть их с квалификацией следующим образом: 'производный_объект-> AbstractBase :: draw()'. – TemplateRex

1

Если вы пытаетесь вызвать initializeFiles() из конструктора FileContainer он будет вызывать FileContainer :: initializeFiles(). Это связано с тем, что конструктор для производного класса еще не выполнен, и поэтому v-таблица для производного класса не была построена.

Также, если FileContainer :: initializeFiles() - это чисто виртуальная функция, тогда вы получите сбой.

Смежные вопросы