【问题标题】:'undefined reference to vtable for' in Case of Constructor/Desconstructor在构造函数/解构函数的情况下“未定义对 vtable 的引用”
【发布时间】:2015-05-25 02:52:06
【问题描述】:

当我使用 c++11 和发布模式在 clang++ 中练习多态性时,我得到了 2 个“未定义对 vtable 的引用”的错误。以下是我的部分代码。

#include <armadillo>
typedef float CHOSENONE;
typedef std::vector<std::vector<CHOSENONE> > fVect2d;
typedef std::vector<CHOSENONE> fVect;
class CfSubSet {
    private:
        fmat m_Data;
        frowvec m_Label;
        int m_NumInstances, m_NumFeatures ;
    public:
        CfSubSet(){
            cout<<"hello! \n" <<endl;
            m_NumInstances = 0;
            m_NumFeatures = 0;
            m_Data.zeros();
            m_Label.zeros();
        }
        CfSubSet(int iNumInstances, int iNumFeatures):m_NumInstances(iNumInstances),m_NumFeatures(iNumFeatures){
            m_Data.resize(iNumInstances,iNumFeatures);
            m_Label.resize(iNumInstances);
        }
        ~CfSubSet(){
            m_Data.reset();
            m_Label.reset();
        }
        inline int getNumInstances(){return m_NumInstances;};
        inline int getNumFeatures(){return m_NumFeatures;};
        inline fmat& getData(){return m_Data;};
        inline fmat& getLabel(){return m_Label;};
};

class CData
{
    protected:
        CfSubSet * m_Test;
        CfSubSet * m_Train;
    public:

        CData(){
            m_Test = new CfSubSet();
            m_Train = new CfSubSet();
        };

        ~CData(){
            delete m_Test;
            delete m_Train;
        };

        virtual void readDataFile(string ifFileTrainName) = 0;
        virtual void readLabelFile(string ifFileLabelFile) = 0;
        virtual void readTestFile(string ifFileTestFile) = 0;
        virtual void readGroundTruthFile(string ifGroundTruthFile) = 0;
};


class CMNISTSet : public CData
    {
    public:
        CMNISTSet() {};
        ~CMNISTSet(){};

        void readDataFile(string ifFileTrainName); 
        void readLabelFile(string ifFileLabelFile); 
        void readTestFile(string ifFileTestFile); 
        void readGroundTruthFile(string ifGroundTruthFile); 

    private:
        void ReadData(string ifFileName, fmat & rfOut); 
        void ReadLabel(string ifFileName, frowvec &rfOut); 
        int reverseInt (int i); 
    };

根据Undefined reference to vtable

解决办法是保证所有不纯的虚方法 被定义。请注意,必须定义析构函数,即使它是 声明为纯虚拟

我已经实现了所有的虚函数,但是在析构函数的情况下,我没有明白这一点,因为我也定义了。我是否错过了代码中必须包含的任何内容?有没有人可以帮忙。提前谢谢你。

更新 1:我把完整的代码放在这里。在 MNISTSet.cpp

#include "MNISTSet.h"
int CMNISTSet::reverseInt (int i){
    unsigned char c1, c2, c3, c4;
    c1 = i & 255;
    c2 = (i >> 8) & 255;
    c3 = (i >> 16) & 255;
    c4 = (i >> 24) & 255;
    return ((int)c1 << 24) + ((int)c2 << 16) + ((int)c3 << 8) + c4;
}

void CMNISTSet::ReadData(string ifFileName, fmat & rfOut){
    ifstream ifs(ifFileName.c_str(),std::ios::in | std::ios::binary);
    int magic_number = 0;
    int number_of_images = 0;
    int rows = 0;
    int cols = 0;

    ifs.read((char*)&magic_number,sizeof(magic_number));
    magic_number= reverseInt(magic_number);
    ifs.read((char*)&number_of_images,sizeof(number_of_images));
    number_of_images= reverseInt(number_of_images);
    ifs.read((char*)&rows,sizeof(rows));
    rows= reverseInt(rows);
    ifs.read((char*)&cols,sizeof(cols));
    cols= reverseInt(cols);

    rfOut = fmat(number_of_images, rows*cols);
    cout << magic_number << " " << number_of_images << " " << rows << " " << cols << endl;

    for(int i = 0; i < number_of_images; i++){

        for(int row = 0; row < rows; row++){
            for(int col = 0; col < cols; col++){
                unsigned char temp = 0;
                ifs.read((char*)&temp,sizeof(temp));
                rfOut(i,rows*row+col) = (CHOSENONE)temp;
            }
        }
    }
}

void CMNISTSet::readDataFile(string ifFileTrainName){
    ReadData(ifFileTrainName, this.m_Train->getData());
}

void CMNISTSet::readTestFile(string ifFileTestFile){
    ReadData(ifFileTestFile, this.m_Test->getData());
}

void CMNISTSet::ReadLabel(string ifFileName, frowvec & rfOut){
    ifstream ifs(ifFileName.c_str(),std::ios::in | std::ios::binary);
    int magic_number = 0;
    int number_of_images = 0;

    ifs.read((char*)&magic_number,sizeof(magic_number));
    magic_number= reverseInt(magic_number);
    ifs.read((char*)&number_of_images,sizeof(number_of_images));
    number_of_images= reverseInt(number_of_images);

    rfOut = frowvec(number_of_images);
    cout << number_of_images << endl;

    for(int i = 0; i < number_of_images; i++){
        unsigned char temp = 0;
        ifs.read((char*)&temp,sizeof(temp));
        rfOut(i) = (CHOSENONE)temp;
    }
}

void CMNISTSet::readLabelFile(string ifFileTestFile){
    ReadLabel(ifFileTestFile, m_Labels);
}

void CMNISTSet::readGroundTruthFile(string ifGroundTruthFile){
    ReadLabel(ifGroundTruthFile, m_GroundTruth);
}

【问题讨论】:

  • override keyword 在这种情况下通常很有帮助。不确定,但在这里也可能会有所帮助。
  • 这可能不是错误的原因,而是make the CData destructor virtual
  • 发布一个显示问题的完整程序。你没有表明你已经定义了对应于纯虚方法等的函数。
  • 我已经更新了代码,你可以看到我已经定义了所有的函数
  • 你的意思是 C++11 吗? C 没有多态性

标签: c++ c++11 inheritance polymorphism


【解决方案1】:

您的子类函数声明必须在某处定义。

为了测试,我将您的覆盖声明更改为:

void readDataFile(string ifFileTrainName) {}
void readLabelFile(string ifFileLabelFile) {}
void readTestFile(string ifFileTestFile) {} 
void readGroundTruthFile(string ifGroundTruthFile) {}

这行得通。

如果您在单独的 .cpp 文件中定义函数。然后你需要指定他们的类。

void CMNISTSet::readDataFile( ... ){ ... }
...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-08
    • 2016-09-26
    • 2014-06-05
    • 1970-01-01
    相关资源
    最近更新 更多