Ответ 1
Совершенно право называть чистую виртуальную функцию не виртуально:
Derived d;
d.Base::method();
Конечно, для этого требуется, чтобы функция была определена, что не соответствует вашему примеру.
Я уверен, что мы все видели код, который выходит из строя из-за ошибки, которая приводит к вызову чистой виртуальной функции. Один простой пример:
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()
, подобное. Я просто подумал, что это забавный головоломщик: -)
Совершенно право называть чистую виртуальную функцию не виртуально:
Derived d;
d.Base::method();
Конечно, для этого требуется, чтобы функция была определена, что не соответствует вашему примеру.
Зависит от того, что вы имеете ввиду с возможным. Здесь тот, который компилируется успешно, но, скорее всего, приведет к ошибке компоновщика:
struct Base
{
virtual void method() = 0;
};
struct Derived : Base
{
void method() { Base::method(); };
};
int main()
{
Derived d;
d.method();
}
Он компилируется, потому что ничто не мешает чистой виртуальной функции фактически иметь тело. Это может быть предусмотрено в одной и той же единице перевода (в отдельном определении) или в другой единицы перевода. Вот почему это ошибка компоновщика, а не компилятор - просто, что функция не имеет тела здесь, не означает, что в ней нет нигде.
Чистая вирутальная функция может иметь реализацию. Лучший пример: чистый виртуальный деструктор должен иметь реализацию, потому что все деструкторы будут вызываться, когда объект уничтожается.
Вывод ошибки компоновщика из ответа @Angew. Не уверен в том, что поведение undefined происходит здесь...
struct Base
{
virtual void method() = 0;
};
void Base::method(){}
struct Derived : Base
{
void method() { Base::method(); };
};
int main()
{
Derived d;
d.method();
}