30

我遇到的问题是,当我为我创建的类调用构造函数时,出现以下错误。

main.cpp:20: 未定义引用`StaticObject::StaticObject(Graphics*, sf::String,
sf::Vector2)'

这个问题可以“修复”,像这样在 main.cpp 中为 .cpp 文件添加一个包含。

...
#include "GameObjects/StaticObject.cpp"
...

虽然这解决了问题,但这似乎是一个糟糕的解决方案,并且与我之前被告知的内容背道而驰。有没有其他方法可以解决这个问题?我正在使用带有 g++ 的 Netbeans 7.3 来编码/编译这个程序。下面是相关代码。

主文件

...

#include <SFML/Graphics.hpp>
#include "Graphics/Graphics.hpp"
#include "GameObjects/StaticObject.hpp"

int main(int argc, char** argv) {

    //SETUP
    Graphics graphics;

    background = new StaticObject(&graphics, "Data/Images/BackgroundPlaceholder.png",  sf::Vector2f(0,0));

...

主文件

...

#include <SFML/Graphics.hpp>
#include "GameObjects/StaticObject.hpp"

...

// Objects
StaticObject *background;
...

静态对象.hpp

#include <SFML/Graphics.hpp>
#include "../Graphics/Graphics.hpp"

class StaticObject{
public:
    StaticObject();
    StaticObject(Graphics *_graphics, sf::String texture_filename, sf::Vector2f _position);
    StaticObject(const StaticObject& orig);
    virtual ~StaticObject();
private:
    // The sprite stores the position
    sf::Sprite *sprite;
    sf::Texture *texture;
};

静态对象.cpp

#include "StaticObject.hpp"
#include <SFML/Graphics.hpp>
#include "../Graphics/Graphics.hpp"

StaticObject::StaticObject(){    
}

StaticObject::StaticObject(Graphics *_graphics, sf::String texture_filename, sf::Vector2f _position) {
    sprite = _graphics->AddSprite(texture_filename);
    sprite->setPosition(_position);
}

StaticObject::StaticObject(const StaticObject& orig) {
}

StaticObject::~StaticObject() {
}

如果我将以下行添加到 main.cpp,错误就会消失。

#include "GameObject/StaticObject.cpp"

谁能解释一下:

  1. 为什么这可以解决问题?

  2. 为什么 .cpp 没有通过包含 .hpp 文件来隐式包含?

  3. 有没有更好的方法来做到这一点?

4

6 回答 6

23

undefined reference错误表明链接器未找到函数/方法(即此处的构造函数)的定义。

StaticObject::StaticObject(Graphics*, sf::String,    sf::Vector2<float>)

以及添加以下行的原因:

#include "GameObject/StaticObject.cpp"

解决了这个问题,它是否将实现作为一部分引入,main.cpp而您的实际实现在StaticObject.cpp. 这是解决此问题的错误方法。

我没有太多使用 Netbeans,但应该有一个选项可以将所有 .cpp 文件添加到单个项目中,以便 Netbeans 负责将所有.o文件链接到单个可执行文件中。

如果StaticObject.cpp内置到它自己的库中(我非常怀疑这里是这种情况),那么您可能必须指定该库所在位置的路径,以便链接器可以找到实现。

这是构建程序时理想的情况:

Compile: StaticObject.cpp -> StaticObject.o
Compile: main.cpp -> main.o
Link: StaticObject.o, main.o -> main_program

尽管在 gcc/g++ 中有一些方法可以跳过所有中间 .o 文件生成并直接生成main_program, 如果您在同一命令行中指定所有源文件(和任何库)。

于 2013-03-22T20:26:45.330 回答
9

链接器找不到 的定义StaticObject,这意味着您尚未编译和链接 StaticObject.cpp。每个 .cpp 文件都需要单独编译,编译器为每个文件生成的目标文件需要提供给链接器。

在 Main.cpp 中包含 StaticObject.cpp 的原因是您告诉预处理器将 StaticObject.cpp 的内容插入到您正在编译的 Main.cpp 中,因此定义成为 Main.cpp 编译输出的一部分。

于 2013-03-22T20:26:22.413 回答
4

包含 cpp 文件会导致编译器将该代码构建为该文件的一部分(您不应该这样做),您需要做的是将 GameObject/StaticObject.cpp 文件编译为其自己的对象,并将 2 个对象链接在一起。

于 2013-03-22T20:31:18.543 回答
2

我不太了解 netbeans,但可能 GameObject/StaticObject.cpp 不包含在要编译的源代码中。

这就是为什么如果您在 main.cpp 中手动包含它,他会找到源代码并且一切正常。

于 2013-03-22T20:27:54.917 回答
1

我有同样的问题,但我的问题是因为我将 Eclipse CDT 与Autotools project一起使用。所以我只好手动添加新的.h.cpp文件到对应的Makefile.am,然后做一个project > reconfigure project,rebuild,就这样了。

于 2016-01-05T00:28:31.697 回答
1

我在 Qt 中遇到了同样的问题,我忘记将类添加到 pro 文件中。显然,如果不将其添加到 pro 文件中,编译器将无法识别它。所以我添加了它,然后再次运行 qmake,这解决了问题。

基本上,您需要在源中添加文件。

于 2020-12-23T18:24:53.903 回答