使用类时链接期间的简单 C++ 未定义引用错误

Simple C++ undefined reference error during linking while using a class

提问人:WillemB 提问时间:9/18/2014 更新时间:9/18/2014 访问量:1648

问:

我想我有一个简单的问题。但到目前为止,我无法解决它,因为我是 C++ 编程的新手。我创建了一个新的 C++ 项目,使代码尽可能简短(因为原始代码要长得多),同时保留我遇到的问题。我在 Stackoverflow 和 Google 上搜索并阅读了大约 50 个相关问题,但到目前为止没有任何帮助我解决它。将所有内容放在一个 cc 和一个 h 文件中是可行的,但这不是我喜欢做的事情。提前感谢您的帮助。

我正在使用 Ubuntu 14.04 / Code::Blocks 13.12 / gcc 和 g++ 4.8.2

问题是我想访问在不同文件中定义的类中的函数,并且在编译工作时(由于 file1.h 中的 extern)链接失败。如果我只是在 file1.h 中放入“Simple S1;”而不是“extern Simple S1;”并将其从 file1.cc 中删除,我会得到一个预期的多重声明错误。显然,“extern”技巧不适用于类,而它适用于变量。

file1.h:

#ifndef FILE1_H
#define FILE1_H

class Simple
{
    private:
    unsigned int length = 10;

    public:
    void SetLength(unsigned int l) {length = l;}
    unsigned int GetLength() {return length;}
};

extern Simple S1;

#endif

file1.cc:

#include <iostream>
#include "file1.h"
#include "file2.h"

int main()
{
    Simple S1;
    unsigned int l = GetL();
    std::cout << "length=" << l << "\n";
    l = 20;
    l = GetL();
    std::cout << "length=" << l << "\n";
    return 0;
}

file2.h:

#ifndef FILE2_H
#define FILE2_H

unsigned int GetL();

#endif

file2.cc:

#include "file1.h"
#include "file2.h"

unsigned int GetL()
{
    return S1.GetLength();
}

构建命令和错误:

g++ -std=c++11 -Wall -fexceptions -g  -c file1.cc -o obj/Debug/file1.o
g++ -std=c++11 -Wall -fexceptions -g  -c file2.cc -o obj/Debug/file2.o
g++  -o bin/Debug/Test obj/Debug/file1.o obj/Debug/file2.o   
obj/Debug/file2.o: In function `GetL()':
file2.cc:6: undefined reference to `S1'
collect2: error: ld returned 1 exit status
C G++ 链接器错误 未定义引用

评论


答:

0赞 CashCow 9/18/2014 #1

如果 S1 是全局的,则必须在全局范围内定义,而不是在 main() 中定义,main() 会在该函数本地创建一个新实例。

在函数中放在 main() 之前。Simple S1;

#include <iostream>
#include "file1.h"
#include "file2.h"

Simple S1;

int main()
{
    unsigned int l = GetL();
    std::cout << "length=" << l << "\n";
    l = 20;
    l = GetL();
    std::cout << "length=" << l << "\n";
    return 0;
}

评论

0赞 WillemB 9/18/2014
也感谢您令人难以置信的快速和正确的响应,我非常专注于我刚刚添加到代码中的整个类事情,以至于我没有看到如此明显的东西。
0赞 CashCow 9/18/2014
我比另一个答案提前了大约一分钟,但你接受了另一个答案。
0赞 WillemB 9/18/2014
对不起,我没有看那个,它只是在我检查了我的问题后首先列出了另一个。没想到我会这么快收到答案哇。更正了接受的答案,尽管我更愿意给你两个学分。
0赞 Baldrickk 9/18/2014
当然,另一种选择是接受它所处理的对象:并用GetL()unsigned int GetL(simple S1){return S1.GetLength();}l=GetL(S1);
0赞 CashCow 9/18/2014
问题是问如何在全球范围内链接。我认为这个问题被简化了。
0赞 Angew is no longer proud of SO 9/18/2014 #2
extern Simple S1;

此声明承诺在代码中的其他位置存在类型的全局对象。但是你永远不会定义这样的对象。你得出的“最接近”的是里面的局部变量,但当然,这是完全不同的事情。S1SimpleS1main()

因此,只需将定义移到以下部分之外:S1main()

Simple S1;

int main()
{
    unsigned int l = GetL();
    std::cout << "length=" << l << "\n";
    l = 20;
    l = GetL();
    std::cout << "length=" << l << "\n";
    return 0;
}

评论

0赞 WillemB 9/18/2014
哇,感谢您令人难以置信的快速和正确的响应,我非常专注于我刚刚添加到代码中的整个类事情,以至于我没有看到如此明显的东西。