首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >我该如何处理这个奇怪的错误呢?

我该如何处理这个奇怪的错误呢?
EN

Stack Overflow用户
提问于 2009-11-08 07:21:42
回答 4查看 6K关注 0票数 1

一切都很好,最后的问题很烦人。编译很好,但链接失败:

代码语言:javascript
复制
bash-3.2$ make
g++ -Wall -c -g Myworld.cc
g++ -Wall -g solvePlanningProblem.o Position.o AStarNode.o PRM.o PRMNode.o World.o SingleCircleWorld.o Myworld.o RECTANGLE.o CIRCLE.o -o solvePlanningProblem

**Undefined symbols:

"vtable for Obstacle", referenced from:
      Obstacle::Obstacle()in Myworld.o

"typeinfo for Obstacle", referenced from:
      typeinfo for RECTANGLEin RECTANGLE.o
      typeinfo for CIRCLEin CIRCLE.o

ld: symbol(s) not found

collect2: ld returned 1 exit status

make: *** [solvePlanningProblem] Error 1**

Obstacle.hh

代码语言:javascript
复制
#ifndef Obstacle_hh 
#define Obstacle_hh

#include <vector>
#include <iostream>

class Obstacle{
public:
    Obstacle(){}
    virtual bool collidesWith(double x,double y);
    virtual void writeMatlabDisplayCode(std::ostream &fs);
    virtual ~Obstacle(){}
};
#endif

我有什么问题?我可以发布任何你需要的代码来分析它。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-11-08 08:21:15

您声明了一个非抽象类Obstacle,但并没有实现它的所有成员函数。

最好将其声明为抽象类:

代码语言:javascript
复制
class Obstacle{
public:
    Obstacle(){} // this is superfluous, you can (and should) remove it
    virtual bool collidesWith(double x,double y) = 0;
    virtual void writeMatlabDisplayCode(std::ostream &fs) = 0;
    virtual ~Obstacle(){}
};

原因是您可以在许多C++编译器中找到一个启发式方法--在定义类的第一个非内联虚拟成员函数(如果它有一个)时,为了避免不必要地为类创建重复的vtable和typeinfos。

您的代码破坏了这种方案:您将Obstacle.hh包含到某个编译单元中,编译器看到一个类ObstaclecollidesWith作为第一个非内联虚拟成员函数,但它没有在当前编译单元中定义,因此编译器认为它可以推迟为该类创建vtable和typeinfo。因为没有collidesWith的定义,所以当程序被链接时,它们都会丢失。

票数 5
EN

Stack Overflow用户

发布于 2009-11-08 07:26:56

显然,您缺少对象文件或库。定义和声明障碍物的对象。

可以在Myworld中引用的头文件(*.h)中查找它,因为这将使您了解Myworld使用的对象背后的cpp/库(通常具有相同的名称)。

编辑,给出Lisa的回复:

不需要,您不需要在源代码中添加任何*.hh文件。问题出在链接时,而不是编译时。

某处不是有一个Obstacle.cpp文件吗?这将需要进行编译,并且需要将相应的.o文件添加到make中的最后一行gcc。

对啰!在看到Obstacle.hh时

这两个虚方法并不是纯虚的,因此编译器希望以某种方式在某个地方定义它们。而且构造函数和析构函数也没有定义。

最简单的方法可能是编写类似这样的代码:

代码语言:javascript
复制
class Obstacle{
public:
    // Obstacle();
    virtual bool collidesWith(double x,double y) = 0;  // = 0 makes them pure virtual
    virtual void writeMatlabDisplayCode(std::ostream &fs) = 0;
    //~Obstacle();
};

或者,您可以声明一个小的不做任何事情的构造函数和析构函数,或者您可以使析构函数成为纯虚的,以强制派生类实现析构函数……

票数 2
EN

Stack Overflow用户

发布于 2009-11-08 08:06:22

类障碍需要一个虚拟析构函数。将析构函数定义更改为:

代码语言:javascript
复制
virtual ~Obstacle();

析构函数的定义还为具有虚函数的类创建了vtable。它还确保通过基类指针删除派生类实例的操作是正确的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1694785

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档