簡體   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