如果未链接使用代码,则未定义对 g++ 中静态常量成员的引用
Undefined reference to static const member in g++ if no using code is linked
我目前正在处理的项目包含三个基本构建目标:
- 核心,包含了几乎所有的类
- 测试,只包含几个测试类和一个主要功能。他们(希望)触及核心中的每一段代码。
- 客户端,只包含一个主要函数,用于从核心创建一个对象并调用当前的Hello World函数。现在 main 完全是空的,它没有做任何事情来消除错误。
linking 错误仅在我构建客户端时出现。它是关于核心中的静态常量,看起来像这样:
class Transition
{
private:
Transition();
...more declarations...
public:
static const Transition NO_TRANSITION
...more declarations...
}
在Map.cpp中的用法:
Transition Map::searchTransition(Coordinate p, Direction d)
{
...code...
return Transition::NO_TRANSITION;
}
这是 g++ 告诉我的:
obj/gpp/Debug/Game/Map/Map.o:Map.cpp: (.rdata$.refptr._ZN10Transition13NO_TRANSIT
IONE[.refptr._ZN10Transition13NO_TRANSITIONE]+0x0): 未定义引用`Transition::NO_TRANSITION'
Map.cpp 也是核心的一部分,它包括 Transition.h,并且 .o 文件就在预期的位置。两个涉及的文件之间没有前向声明。
最让我困扰的是:只有在我构建客户端时才会发生这种情况。如果我 link 核心与测试 类 而不是它们的主要部分,它工作得很好,这意味着只有更多代码需要 linked。唯一删除的是一个很小甚至是空的主函数,它被一个实际使用 Map 和 Transition 的大得多的函数所取代。
此外,static const 不是新的,过去从未引起过问题。由于测试接受了它,我认为一切都很好,但显然只要测试linked 就可以了。
我已经尝试在一个较小的项目中重现错误,生成文件(大部分)相同,但错误不会出现。我完全不知道重要的区别是什么。
我在 cygwin 下使用 g++ 4.8 和 -std=c++11。 Visual Studio 可以毫无问题地接受相同的代码,并且在 true linux 下我还不能测试,尽管我希望它与 cygwin 相同。
有人知道这里可能出了什么问题吗?
编辑:"strange" 行为的发生是因为在测试中实际上有一个 Transition::NO_TRANSITION 的定义。
您必须定义静态变量。在您的 CPP 中,添加此行。
static const Transition::Transition NO_TRANSITION
那就行了。
您只是声明了它,因此没有存储其数据的物理位置。您应该将定义添加到您的 Transition 源和 link 使用您的测试创建的目标文件。
// Transition.cpp
#include "transition.h"
const Transition Transition::NO_TRANSITION;
请注意,linker 以某种方式延迟工作,即不会搜索您未引用的符号,因此未使用实际 NO_TRANSITION
物理位置的旧代码已编译并link很好。
我目前正在处理的项目包含三个基本构建目标:
- 核心,包含了几乎所有的类
- 测试,只包含几个测试类和一个主要功能。他们(希望)触及核心中的每一段代码。
- 客户端,只包含一个主要函数,用于从核心创建一个对象并调用当前的Hello World函数。现在 main 完全是空的,它没有做任何事情来消除错误。
linking 错误仅在我构建客户端时出现。它是关于核心中的静态常量,看起来像这样:
class Transition
{
private:
Transition();
...more declarations...
public:
static const Transition NO_TRANSITION
...more declarations...
}
在Map.cpp中的用法:
Transition Map::searchTransition(Coordinate p, Direction d)
{
...code...
return Transition::NO_TRANSITION;
}
这是 g++ 告诉我的:
obj/gpp/Debug/Game/Map/Map.o:Map.cpp: (.rdata$.refptr._ZN10Transition13NO_TRANSIT IONE[.refptr._ZN10Transition13NO_TRANSITIONE]+0x0): 未定义引用`Transition::NO_TRANSITION'
Map.cpp 也是核心的一部分,它包括 Transition.h,并且 .o 文件就在预期的位置。两个涉及的文件之间没有前向声明。
最让我困扰的是:只有在我构建客户端时才会发生这种情况。如果我 link 核心与测试 类 而不是它们的主要部分,它工作得很好,这意味着只有更多代码需要 linked。唯一删除的是一个很小甚至是空的主函数,它被一个实际使用 Map 和 Transition 的大得多的函数所取代。
此外,static const 不是新的,过去从未引起过问题。由于测试接受了它,我认为一切都很好,但显然只要测试linked 就可以了。
我已经尝试在一个较小的项目中重现错误,生成文件(大部分)相同,但错误不会出现。我完全不知道重要的区别是什么。
我在 cygwin 下使用 g++ 4.8 和 -std=c++11。 Visual Studio 可以毫无问题地接受相同的代码,并且在 true linux 下我还不能测试,尽管我希望它与 cygwin 相同。
有人知道这里可能出了什么问题吗?
编辑:"strange" 行为的发生是因为在测试中实际上有一个 Transition::NO_TRANSITION 的定义。
您必须定义静态变量。在您的 CPP 中,添加此行。
static const Transition::Transition NO_TRANSITION
那就行了。
您只是声明了它,因此没有存储其数据的物理位置。您应该将定义添加到您的 Transition 源和 link 使用您的测试创建的目标文件。
// Transition.cpp
#include "transition.h"
const Transition Transition::NO_TRANSITION;
请注意,linker 以某种方式延迟工作,即不会搜索您未引用的符号,因此未使用实际 NO_TRANSITION
物理位置的旧代码已编译并link很好。