-std=c++11 未定义对 vtable 的引用 -- 国际象棋

-std=c++11 undefined reference to vtable for -- Chess

我有一个问题,但我无法解决(google)。作为练习,我写了一个关于国际象棋的程序。 有一般片class:

pieces.h :

#ifndef PIECES_H
#define PIECES_H

[...]

class piece{
public:
    bool dark; //0 = light, 1 = dark
    virtual std::vector<position> sovereign_movement();
    types identify; // enum types = {pawn, knight, king, etc...}
    position pos;
    std::vector<position> horizontal(position a);
    std::vector<position> vertical(position a);
    std::vector<position> plus90(position a);      //basic moves
    std::vector<position> minus90(position a);
    std::vector<position> Lshape(position a);

    piece() : identify(non), pos(position(1,1)) {}
    virtual ~piece() {}
};

class Pawn : public piece{
public:
    Pawn() { identify = pawn; }
    std::vector<position> sovereign_movement() {std::vector<position> sol; return sol;}
    ~Pawn() = default;
};
[...]

#endif //PIECES_H

我的 main 用于测试:

#include "pieces.h"

int main()
{
   piece a;
   vector<position> test = a.horizontal();
   for(unsigned int i=0; i<test.size() ;i++)
       {
        cout << test[i].Pconvert() << endl; /// position::Pconvert() just make string
       }
return 0;
}

我有一个 pieces.cpp 文件,其中定义了较长的方法:

#include "pieces.h"
#ifndef PIECES_H
#define PIECES_H

std::vector<position> piece::horizontal(position a){
    std::vector<position> sol;
    for(int i = 1;i<=8;i++){
        sol.push_back(position(i,a.y));
        if(i==a.x){sol.pop_back();}
    }
    return sol;
}

[...]

#endif //PIECES_H

为此,我在头文件中得到 undefined reference to piece::horizontal(position)undefined reference to vtable for piece 构造函数和析构函数。

如果我执行我的析构函数摘要 (virtual ~piece() = 0),我会得到: error: cannot declare variable 'a' to be of abstract type 'piece', because the following functions are pure within 'piece': virtual piece::~piece()

之后,我编写了所有派生的 classes 的默认析构函数,但写的是一样的。在此之后,我以这种方式修改我的主要内容(Pawnpiece 的派生 classes 之一):

int main()
{
    piece* a = new Pawn();
    vector<position> test = a->horizontal(a->pos);
    for(unsigned int i=0;i<test.size();i++){
        cout << test[i].Pconvert() << endl;
    }
    return 0;
}

然后我得到:undefined reference to 'piece::horizontal(position)' 和 .h 中对 piece 的析构函数的未定义引用,因此 round 被关闭。

有人可以帮助我吗? 谢谢

当您包含 header 文件时,该文件的内容将替换 #include 行。所以当pieces.cpp这样开始时:

#include "pieces.h"
#ifndef PIECES_H
#define PIECES_H

std::vector<position> piece::horizontal(position a){
    std::vector<position> sol;
    for(int i = 1;i<=8;i++){
        sol.push_back(position(i,a.y));
        if(i==a.x){sol.pop_back();}
    }
    return sol;
}

#endif //PIECES_H

pre-processor处理完#include后变成下面的样子。

#ifndef PIECES_H
#define PIECES_H
class piece{
public:
    bool dark; //0 = light, 1 = dark
    virtual std::vector<position> sovereign_movement();
    types identify; // enum types = {pawn, knight, king, etc...}
    position pos;
    std::vector<position> horizontal(position a);
    std::vector<position> vertical(position a);
    std::vector<position> plus90(position a);      //basic moves
    std::vector<position> minus90(position a);
    std::vector<position> Lshape(position a);

    piece() : identify(non), pos(position(1,1)) {}
    virtual ~piece() {}
};
#endif //PIECES_H
#ifndef PIECES_H
#define PIECES_H

std::vector<position> piece::horizontal(position a){
    std::vector<position> sol;
    for(int i = 1;i<=8;i++){
        sol.push_back(position(i,a.y));
        if(i==a.x){sol.pop_back();}
    }
    return sol;
}

#endif //PIECES_H

接下来,说明 PIECES_H 宏。我会在继续时注释掉预处理行。

// #ifndef PIECES_H  -- PIECES_H is not defined yet, so proceed.
// #define PIECES_H  -- now PIECES_H is defined.
class piece{
public:
    bool dark; //0 = light, 1 = dark
    virtual std::vector<position> sovereign_movement();
    types identify; // enum types = {pawn, knight, king, etc...}
    position pos;
    std::vector<position> horizontal(position a);
    std::vector<position> vertical(position a);
    std::vector<position> plus90(position a);      //basic moves
    std::vector<position> minus90(position a);
    std::vector<position> Lshape(position a);

    piece() : identify(non), pos(position(1,1)) {}
    virtual ~piece() {}
};
// #endif //PIECES_H -- end of the earlier #ifndef
// #ifndef PIECES_H  -- PIECES_H is still defined from earlier. So skip ahead.
// All these lines are omitted from compilation
// #endif //PIECES_H -- end of the earlier #ifndef

由于 header 守卫的 mis-use,预处理器刚刚删除了 pieces.cpp 的内容。 Header 守卫属于 header(另见 A: C++ Header Guard Syntax and Header Placement)。将它们从您的源文件中取出,它应该按预期编译。