2013-04-10 4 views
4

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

  • Почему объявить конструктор как виртуальные бессмысленна?
  • Что происходит, когда я вызываю виртуальную функцию из конструктора? Используется ли виртуальная таблица?
+0

Что означает «пройти»? – Beta

+0

Grammar-corrected :) –

+0

Этот связанный вопрос содержит некоторую полезную информацию: http://stackoverflow.com/questions/962132/calling-virtual-functions-inside-constructors – Chad

ответ

2

При вызове конструктора фактический тип (еще не существующего) объекта известен очень точно. Поэтому вызов конструктора никогда не будет косвенным. (Только виртуальные функции вызываются косвенно при вызове через указатель/ссылка.)

BaseClass *x = new SubClass(); 

Вызов виртуальной функции в конструкторе не делать то, что вы могли бы ожидать. Поскольку подкласс еще не инициализирован, виртуальная функция в конечном классе не может быть вызвана (в настоящее время v-таблица указывает на класс исполняемого конструктора).

class BaseClass { 
    BaseClass() { 
     call(); 
    } 
    virtual void call() { 
     std::cout << "BaseClass!"; 
    } 
}; 

class SubClass : public BaseClass { 
    SubClass() : BaseClass() 
    { 
    } 

    void call() { 
     std::cout << "SubClass!"; 
    } 
}; 

http://ideone.com/9aQVIc

+1

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

+0

Исправлено. Я не был уверен; Я знал, что буду помнить это неправильно. Теперь я помню. См. Мою коррекцию. – leemes

+0

@David Итак, просто чтобы уточнить, если у вас был класс SubSubClass: public SubClass', и вы пытались вызвать 'call()' из конструктора SubClass', он вызывал бы 'SubClass :: call()'? – JBentley

3

Почему объявить конструктор как виртуальные бессмысленна?

Перед тем как конструктор выполняется, объект не существует, поэтому нет такого понятия, как переопределение.

Что происходит, когда я вызываю виртуальную функцию из конструктора? Используется ли виртуальная таблица?

Он может. В большинстве случаев, если вызов выполняется непосредственно из конструктора, компилятор может пропустить динамическую отправку, так как он знает, что на данный момент находится конечный переопределитель. Но он не должен выполнять эту оптимизацию, и даже если он может сделать это непосредственно в конструкторе, он не сможет этого сделать, если вы вызываете не виртуальную функцию, которая, в свою очередь, вызывает виртуальную функцию. Поскольку не виртуальная функция может быть вызвана для объектов производных типов, она должна использовать механизм виртуальной диспетчеризации.

1

Why declaring a constructor as virtual is meaningless.

При вызове конструктора виртуальная таблица не будет доступна в памяти. Объявление чего-то виртуального в C++ означает, что он может быть переопределен подклассом текущего класса, однако конструктор вызывается при создании объекта-объекта, в то время вы не можете создавать подкласс класса, который должен быть создавая класс, поэтому никогда не будет необходимости объявлять конструктор виртуальным. Поэтому в C++ нет такой вещи, как virtual constructor.

What happens when I call a virtual function from a constructor? Is the virtual table used too

См C++ FAQ ссылки о подробном объяснении этого вопроса.

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