2017-03-07 107 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'; 
}