Подтвердить что ты не робот

При каких условиях генерируется чистый виртуальный метод?

Я читал во многих местах (например, здесь) о людях, получающих "чистый виртуальный метод, называемый" ошибка и сбой программы "в время выполнения. Этот ответ говорит, что

Большинство компиляторов назначают такие записи vtable заглушке, которая испускает ошибку перед прерыванием программы.

и этот говорит, что Itanium ABI указывает, что это за штука.

Проблема в том, что все мои попытки увидеть это поведение в действии пойманы компилятором (GCC 6.4.1) в время компиляции как undefined ссылки. Например, при вызове чистой виртуальной функции из конструктора абстрактного класса я получаю предупреждение

pure virtual ‘virtual int X::f()’ called from constructor

но в то же время для X::f() ничего не генерируется вообще, поэтому за ним следует

undefined reference to 'X::f()'

из компоновщика, и компиляция не выполняется. Это кажется довольно надежным способом предотвращения ошибки во время выполнения. В какой ситуации мой компилятор действительно должен был бы создать вышеупомянутый заглушка? Или он достаточно умен, чтобы обнаружить все возможные патологические ситуации достаточно рано?

4b9b3361

Ответ 1

Обычно он будет вызван косвенно изнутри конструктора. Вот минимальный пример:

#include <iostream>

struct X {
    virtual void foo() = 0;
    void bar() { foo(); }
    X() { bar(); std::cout << "X"; }
};

struct Y : X {
    void foo() override {}
};


int main() {
    Y y;
    return 0;
}

Компилятор обязан привязать вызов статически, если он непосредственно появляется внутри c'tor (и, следовательно, может дать полезное сообщение об ошибке для чистой виртуальной функции). Но когда вызов косвенный, из другого члена он должен быть динамически отправлен.

Естественно, что часть Y еще не построена во время построения X, поэтому вся вещь рушится сама по себе в пламени поведения undefined.

Пример в реальном времени - с заглушкой на работе