C ++ виртуальная функция не найдена - PullRequest
1 голос
/ 17 августа 2010

У меня есть класс, предназначенный для импорта / экспорта данных в одном из нескольких различных форматов. Каждый формат должен иметь точно такой же интерфейс, поэтому я реализую его как базовый класс с кучей виртуальных методов и производным классом для каждого конкретного формата:

#ifndef _IMPORTEXPORT_H_
#define _IMPORTEXPORT_H_

#include "stdio.h"

enum EXPORT_TYPE {
    EXPORT_INI = 1,
};

class exportfile {
public: 
    virtual ~exportfile();

    static exportfile * openExportFile(const char * file, EXPORT_TYPE type);

    virtual void startSection(int id) = 0;
    virtual void endSection() = 0;

protected:
    exportfile(const char * file);
    FILE * hFile;

};

class iniexportfile : public exportfile {
public:
    iniexportfile(const char * file) : exportfile(file) { }

    void startSection(int id);
    void endSection();
private:
    bool inSection;

};

#endif

Это базовый класс (exportfile) и один из производных классов (iniexportfile).

Реализация этих методов такова:

#include "importexport.h"

#include <exception>
#include <assert.h>

exportfile * openExportFile(const char * file, EXPORT_TYPE type) {
    switch(type) {
        case EXPORT_INI:
            return new iniexportfile(file);
        default:
            return NULL;
    }
}

exportfile::exportfile(const char * file) {

        this->hFile = fopen(file, "w");

        if(this->hFile == 0) {
            throw new std::exception("Unable to open export file");
        }
}

exportfile::~exportfile() {
    assert(this->hFile != 0);

    this->endSection();

    fclose(this->hFile);
    this->hFile = 0;
}

void iniexportfile::startSection(int id) {
    assert(this->hFile != 0);

    fprintf(this->hFile, "[%d]\r\n", id);

    this->inSection = true;
}

void iniexportfile::endSection() {
    this->inSection = false;
}

(Обратите внимание, что класс явно не завершен.)

Наконец, у меня есть метод испытания:

#include "importexport.h"

#include <exception>

using namespace std;

void runImportExportTest() {
    iniexportfile file("test.ini");

    file.startSection(1);

    file.endSection();
}

В любом случае, все это прекрасно компилируется, но когда связывается, компоновщик выдает эту ошибку:

error LNK2001: unresolved external symbol "public: virtual void __thiscall exportfile::endSection(void)" (?endSection@exportfile@@UAEXXZ)   importexport.obj

Почему он ищет exportfile::endSection(), когда он помечен как чисто виртуальный? Разве я как-то не сделал это чисто виртуальным? Или я был избалован C # и полностью испортил эти виртуальные функции?

Кстати, это Visual Studio 2008. Думаю, я должен упомянуть об этом где-то.

1 Ответ

2 голосов
/ 17 августа 2010

К тому времени, когда этот дтор вызывается:

exportfile::~exportfile() {
    assert(this->hFile != 0);

    this->endSection();

    fclose(this->hFile);
    this->hFile = 0;
}

компилятор "размотал" vtable, поэтому он преобразуется в функцию exportfile::endSection() - он не будет вызывать производную версию. Вам нужно будет разработать другой метод очистки.

См. «Никогда не вызывать виртуальные функции во время строительства или разрушения» .

...