Юридически ссылаясь на чистую виртуальную функцию

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

struct Base
{
    Base() { method(); }

    virtual void method() = 0;
};

struct Derived : Base
{
    void method() {};
};

int main()
{
    Derived d;
}

В этом случае вызов method() в конструкторе Base специально упоминается как поведение undefined в соответствии с разделом 10.4/6 стандарта С++, поэтому неудивительно, что мы закончили сбой. (Оба g++ и Clang предупреждают об этом, и на самом деле ссылка не работает с g++ с помощью этого примера, хотя Clang преуспевает.)

Но, просто для удовольствия, может ли кто-нибудь придумать способ вызвать чистую виртуальную функцию, которая не полагается на поведение undefined?

(я полагаю, вы могли бы утверждать, что если такой метод существует, то есть дефект в стандарте С++, но мне просто интересно...)

EDIT: Несколько ответов ребята и спасибо, но я должен был четко указать, что я понимаю, что законно делать не виртуальный вызов чистой виртуальной функции (где-то существует определение), Я больше задавался вопросом, есть ли какая-нибудь умная лазейка в законах, которая может привести к виртуальному вызову, и, скорее всего, к сбою в общем случае отсутствия определения.

Например, возможно, с помощью множественного наследования можно было бы сделать некоторые умные (законные) актеры, но в итоге получилось "неправильное" (не реализованное) PV method(), подобное. Я просто подумал, что это забавный головоломщик: -)

Ответ 1

Совершенно право называть чистую виртуальную функцию не виртуально:

Derived d;
d.Base::method();

Конечно, для этого требуется, чтобы функция была определена, что не соответствует вашему примеру.

Ответ 2

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

struct Base
{
    virtual void method() = 0;
};

struct Derived : Base
{
    void method() { Base::method(); };
};

int main()
{
  Derived d;
  d.method();
}

Живой пример

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

Ответ 3

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

Ответ 4

Вывод ошибки компоновщика из ответа @Angew. Не уверен в том, что поведение undefined происходит здесь...

struct Base
{
    virtual void method() = 0;
};

void Base::method(){}

struct Derived : Base
{
    void method() { Base::method(); };
};

int main()
{
  Derived d;
  d.method();
}

Live Demo