Простое наследование приводит к ошибке Vtable

#c #eclipse #eclipse-cdt

#c #eclipse #eclipse-cdt

Вопрос:

Итак, я пытаюсь скомпилировать этот простой код:

 // In Test.h
#include <iostream>
using namespace std;

class A{

public:
    virtual string f (stringamp;);
};

class B : public A{

public:
    B (string);
    string f (stringamp;);
};

// In Test.cpp
#include <iostream>
#include "Test.h"
using namespace std;


B :: B (string row){
    cout << "HERE";
}

string B :: f (stringamp; x){
    cout << "Test";
}
  

Это кажется достаточно простым, но я продолжаю получать Undefined reference to 'vtable for A' ошибку (компилятор MINGW с Eclipse IDE). Когда я удаляю реализацию конструктора для B, код компилируется нормально. Чего мне не хватает или это ошибка компоновщика?

Комментарии:

1. Нет. Код, который я написал, — это все, что есть, кроме основного, который имеет простой return 0

Ответ №1:

Я думаю, вам либо нужно сделать A::f(stringamp;) абстракцию, написав = 0 в конце объявления, либо фактически предоставить реализацию A::f

Поскольку в настоящее время виртуальная функция A::f не существует, компилятор не может создать для нее vtable (таблицу виртуальных функций).

Комментарии:

1. Вы выиграли : ). Какие-либо причины, по которым функция должна быть чисто виртуальной, а не только виртуальной, и почему удаление реализации конструктора позволяет ей компилироваться?

2. Только виртуальная (неабстрактная) функция ожидает, что реализация функции создаст vtable. vtable в основном содержит адреса всех виртуальных функций. Понятия не имею, почему удаление конструктора допускает компиляцию (этого не должно быть). Проблема рано или поздно возникнет в другом месте…

3. @ShardulUpadhyay: Вы только что объявили функцию и не определили ее. Вам нужно определить функцию, чтобы компоновщик ссылался на ее скомпилированное определение. У чисто виртуальной функции может не быть определения, и, следовательно, будет работать чисто виртуальная функция, или вам нужно ее определить.

4. Конечно, вы могли бы также предоставить реализацию по умолчанию ( virtual string f (stringamp;) {} ) в базовом классе, и компилятор был бы доволен. Но если логически не имеет смысла, чтобы версия базового класса f() имела impl, тогда она должна быть чисто виртуальной, как упоминал Cygnus.

5. @thekashyap: учитывая пример кода, трудно сказать, нужно ли, чтобы функция была чисто виртуальной или нет. Для записи функция может быть чисто виртуальной и все же иметь определение, и да, это помогает в определенных случаях.