2017-03-07 111 views
2

我正嘗試在C++中創建並鏈接一個靜態庫。我有兩個文件:
helloWorld.cppG ++/C++無法鏈接庫

#include <iostream> 

    int main(int argc, char const *argv[]) { 
    std::cout << "I'm inside main." << '\n'; 
    printHello(); 
    return 0; 
} 

libraryHello.cpp

#include <iostream> 

void printHello() { 
    std::cout << "Hello" << '\n'; 
} 

我運行這些命令(基於http://www.techytalk.info/c-cplusplus-library-programming-on-linux-part-one-static-libraries/):

​​

前兩位順利,當試圖編譯主文件時出現這樣的錯誤:

helloWorld.cpp: In function ‘int main(int, const char**)’: 
helloWorld.cpp:5:14: error: ‘printHello’ was not declared in this scope 

它看起來好像根本沒有加載它並且找不到printHello。編譯,鏈接或其他任何事情時,我有什麼錯誤嗎?我想要做的就是使用靜態庫從main調用printHello()過程並將其鏈接到helloWorld.cpp。

我的編譯器:G ++ 5.4.0,操作系統:Ubuntu的16.04 32位

回答

0

你仍然需要有一個向前聲明

void printHello(); 

main()之前。

否則,編譯器不知道應該如何調用該函數。

通常的方法是將其放入相應的頭文件中,並將其包含在其他翻譯單元中。

3

你沒在使用前聲明函數:

#include <iostream> 

void printHello(); /// <-- this was missing  

int main(int argc, char const *argv[]) { 
    std::cout << "I'm inside main." << '\n'; 
    printHello(); 
    return 0; 
} 

您一切準備就緒所需要的鏈接,而不是編譯。總的想法是這樣的:編譯器需要聲明爲您使用的每個函數。就是說,它必須知道它的名字和簽名。

編譯器現在將檢查函數調用是否對給定簽名有效,並留下函數調用的佔位符。由鏈接器來解決這些佔位符,並將其替換爲被調用函數的實際地址。

因此,鏈接器必須爲該函數找到匹配的定義,即實際的實現。如果你只是聲明函數,但忘了定義它,編譯會很高興地成功,但鏈接器會抱怨一個未解決的參考。

該拆分允許您單獨編譯不同的源文件:每個源文件需要知道它使用的每個函數的聲明,但不需要定義。這足以讓編譯器確保調用者正確使用該函數。聲明通常放在頭文件中,以確保實現和調用者對函數簽名是什麼有一致的理解,即使它們駐留在不同的源文件中。

2

helloWorld.cpp

#include <iostream> 
#include <libraryHello.h> 
using namespace std; 

int main(int argc, char const *argv[]) 
{ 
    cout << "I'm inside main." << '\n'; 
    printHello(); 
    return 0; 
} 

libraryHello。H(您需要添加此文件)

#ifndef LIBRARYHELLO_H 
#define LIBRARYHELLO_H 

void printHello(); 

#endif // LIBRARYHELLO_H 

libraryHello.cpp

#include <iostream> 
#include <libraryHello.h> 
void printHello() { 
    std::cout << "Hello" << '\n'; 
}