Функция, объявленная как Virtual в производном классе, не выполняется, вместо этого выдана ошибка компиляции. Почему?

Я понимаю виртуальную функцию и vTable, поэтому извините, если это тривиальный вопрос, чтобы задать ….

Основываясь на концепции vTable и vPtr, объясненной людьми, я понял и ожидаю, что нижеприведенная программа должна работать, но она дает ошибку.

Постановка задачи:
В приведенном ниже примере, согласно пониманию, класс B должен иметь «vTable», содержащий функции f2 () и f3 (). Не так ли?
(поскольку f2 () наследуется от класса A, но переопределяется, а f3 становится виртуальным в самом классе B)

но при вызове функции obj-> f3 (); «Это дает ошибку, как показано ниже, я все еще задаюсь вопросом, почему это так?

ОШИБКА :
В функции ‘int main ()’:
31:10: ошибка: у класса A нет члена с именем f3

// Example program
#include <iostream>
#include <string>

using namespace std;
class A
{
public:
void f1() {cout<<"A::f1"<<endl;}
virtual void f2() {cout<<"A::f2"<<endl;}
};

class B: public A
{
public:
void f1() {cout<<"B::f1"<<endl;}
void f2() {cout<<"B::f2"<<endl;}
virtual void f3() {cout<<"B::f3"<<endl;}
};int main()
{
A* obj = new B();
obj->f1();      // Early Binding (EB)
obj->f2();      // Late Binding (LB)
obj->f3();      // Error (though was expecting LB since f3 is virtual)
}

ОШИБКА :
В функции ‘int main ()’: 31:10: ошибка: у класса A нет члена с именем ‘f3’

0

Решение

Детали реализации (vtable или нет) не имеют значения. В глазах стандарта (и, следовательно, компилятора) ваш код неверен, потому что A нет метода f3() а также obj имеет тип A*, вот и все.

3

Другие решения

Прежде чем пытаться описать семантику любой инструкции C ++, вам необходимо вернуться к самым фундаментальным концепциям C ++ (которые представляют собой сложный вариант фундаментальных концепций C): C ++ — это скомпилированный язык со статической типизацией.

Как в C, в C ++ имена ищутся и связываются во время компиляции: любое используемое имя должно ссылаться на видимое объявление. Единственные имена, которые могут быть найдены компилятором, это имена в классе, обозначенном выражением. (Выражения являются синтаксическими конструкциями, они существуют в время компиляции.)

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

C ++ также поддерживает динамическую полиморфность через виртуальные функции; это не делает язык динамически типизированным; основы неизменны: каждое выражение имеет тип, определяемый применением правил на основе его синтаксиса и видимых объявлений (видимых имен объектов, функций и т. д.).

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

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

obj->f3();      // Error (though was expecting LB since f3 is virtual)

когда obj имеет тип указателя obj->something такой же как (*obj).something; а также obj является локальной переменной, определенной как

A* obj = (...something not relevant for the argument...);

так obj имеет тип A* а также *obj имеет тип A который является классом, определенным как:

class A
{
public:
void f1() {cout<<"A::f1"<<endl;}
virtual void f2() {cout<<"A::f2"<<endl;}
};

Там нет декларации любого члена f3 виден в классе, обозначенном выражением *obj, Так что зов плохо сформирован. Это недопустимо во время компиляции, и компилятор отклоняет его.

И это полнота соответствующего анализа этой плохо сформированной линии. Остальное не имеет значения в статически типизированном языке. Производные классы, не названные в Соответствующий код (который является просто объявленным типом obj и выражение, которое определяет, где выполняется поиск по имени, *obj) не имеет значения. Это сущность статической типизации.

Кроме того, если сделать достоверность кода зависимой от других классов, не названных напрямую (классы, которые могут быть типом объекта, созданного во время выполнения, на которое ссылается какое-либо выражение), это сделает обнаружение даже простой опечатки невозможной во время компиляции.

0

По вопросам рекламы [email protected]