繁体   English   中英

未定义的引用(带有静态库的g ++编译)

[英]Undefined reference to (g++ compilation with static library)

项目文件是这样的:

source
  parser
    parser.cpp
    parser.hpp
  brain
    brain.cpp
    brain.hpp

我首先运行了以下两个命令(pwd source/brain/ ):

g++ -c brain.cpp -o brain.o
ar rvs brain.a brain.o

我将brain.abrain.hpp复制到了source/parser/ 然后我运行了以下命令(pwd source/parser ):

g++ parser.cpp brain.a -o parser

我得到了这个错误:

/tmp/cceGRLZn.o: In function `main':
parser.cpp:(.text+0x1cc): undefined reference to `std::brain<long long>::brain()'
parser.cpp:(.text+0x205): undefined reference to `std::brain<long long>::init(int)'
parser.cpp:(.text+0x26b): undefined reference to `std::brain<long long>::work()'
parser.cpp:(.text+0x2a4): undefined reference to `std::brain<long long>::clear()'
parser.cpp:(.text+0x2ec): undefined reference to `std::brain<long long>::~brain()'
parser.cpp:(.text+0x322): undefined reference to `std::brain<long long>::~brain()'
/tmp/cceGRLZn.o: In function `int parser_extract_args<long long>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, int, short&, std::brain<long long>&)':
parser.cpp:(.text._Z19parser_extract_argsIxEiRSsiRsRSt5brainIT_E[int parser_extract_args<long long>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, int, short&, std::brain<long long>&)]+0x17b): undefined reference to `std::brain<long long>::push_back(long long)'
parser.cpp:(.text._Z19parser_extract_argsIxEiRSsiRsRSt5brainIT_E[int parser_extract_args<long long>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, int, short&, std::brain<long long>&)]+0x37a): undefined reference to `std::brain<long long>::push_back(long long)'
collect2: ld returned 1 exit status

源文件:

brain.cpp [http://ideone.com/GNUxmH][1]
brain.hpp [http://ideone.com/M2IFAI][2]
parser.cpp [http://ideone.com/fJRzhD][3]
parser.hpp [http://ideone.com/mj6dST][4]

我该怎么办?

第一件事: 不要向std名称空间添加任何实体 这为您的程序提供了Undefined Behavior

从您的消息看来,您似乎已经将一个名为brain的类添加到了std名称空间。 std名称空间中删除brain ,然后将其放入您的某些名称空间中。 您可以添加到std名称空间的唯一一件事就是属于std名称空间的模板的特殊化

其次, 除非提供在整个程序中使用的类模板的显式实例化否则 应将类模板的成员函数的定义放在包含其声明的同一头文件中 ,以确保它们在实例化中可见点。

将它们放到一个单独的.cpp文件中,使编译器无法为您从包含其定义的翻译单元之外的其他翻译单元调用的成员函数生成代码。 关于StackOverflow的此问与答可能也对您有所帮助。

我敢打赌,您在.cpp文件中实现了类模板brain的成员函数。 您需要在头文件中提供模板定义,以便编译器在看到模板实例时可以生成适当的代码。 因此,将brain.cpp的内容上移到brain.h

作为示例,请考虑以下三个文件:

  • test.h

     template <typename T> struct test { void foo(T); }; 
  • test.cpp

     #include "test.h" template <typename T> void test<T>::foo(T x) { // do something with x } 
  • main.cpp

     #include "test.h" int main() { test<int> t; t.foo(5); } 

每个.cpp分别编译,然后链接在一起。 假设您是编译器,而您正在尝试编译main.cpp 您将看到代码想要使用以T实例化为inttest模板。 因此,现在您需要为test<int>::foo生成适当的代码,但是要做到这一点,您需要了解函数的定义。 不幸的是,您尚未看到它,因此无法编译该程序。

相反,应该将foo的定义移到头文件中,以产生以下两个文件程序:

  • test.h

     template <typename T> struct test { void foo(T); }; // Alternatively, you can define this up in the class definition void test<T>::foo(T x) { // do something with x } 
  • main.cpp

     #include "test.h" int main() { test<int> t; t.foo(5); } 

请注意,您不应在std名称空间中添加自己的声明:

如果其添加声明或定义名字空间内对空间std或一个命名空间一个C ++程序的行为是未定义std除非另有规定。

您需要用所需的类型声明大脑模板类的实例,因此在brain.cpp中,在文件末尾应放置:

template class brain <long long> ;

编译brain.cpp时,除非在那里有模板说明符,否则它将不会创建任何可链接的代码,因为如果没有类型声明,它将无法实例化模板类。 也就是说,使用模板类时,最好将它们保留为纯头文件

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM