对C++引用库的理解

情景

创建两个静态库 libA 和 libB,libB依赖libA。创建一个程序App引用 libB

关系为:App -> libB -> libA

一般做法是:

创建完libA后编译生成静态库,创建libB时引用该静态库并将libA的头文件复制到libB项目中进行引用。

App对libB的引用也是导入它的静态库和头文件。

可不可以不用头文件?

可以,头文件只其申明作用,你完全可以自己写该声明。事实上,#include 只是在编译时起作用,它仅仅将include的文件全量复制到源文件中。故和你自己写是一样的。

头文件和源文件名称能否不同

可以,还是上面说的,include仅仅将内容原封不动复制进源文件,所以和头文件命名没有什么关系。

如何在App中使用libA中定义的类和方法

如果是java程序,那么你完全可以直接在App项目中声明和使用libA中的类和方法,我认为这也是符合直觉的。

但在c++中,貌似有一条不成文的规定就是任何东西都需要先声明再使用,所以,若想在App中调用libA中的方法,要么你include libA的头文件,要么你手动声明需要调用的方法,然后就可以直接调用,至于调用的方法体,c++程序会在链接步骤自动找到。

举例:

App.cpp(一个Qt的示例程序)

pch.h

libA.h

extern 关键字

我在libB中定义了一个变量,我想在App中使用它,如果你这个变量定义在libB的头文件中这样做是没问题的,但如果你将其定义在了cpp文件中,那你在App中仅引入libB的头文件还是访问不到该变量。

此时,你就可以在头文件中使用extern关键字再次声明定义在cpp中的变量,然后在App中就可以使用了。

例如:

# libB.h
...
class MyClass{...}
extern int num;
extern MyClass mc;
...
# libB.cpp
...
int num = 1;
MyClass mc = MyClass();
...
# App.cpp
#include "libB.h"
...
int main()
{
    std::cout << num << ", " << mc.somproperties;
}
...

但是我测试了下,貌似不能作用与class

extern class MyClass;  // 这样貌似不行,我想如果可以这样的话是不是就能实现java中的那种链式引用的效果了(App中直接调用libA中定义的类而不用引入libA的头文件)

声明和定义

int num = 1;  // 定义
extern int num;  // 声明

定义就是在堆中开辟了一块内存并在栈中创建了其引用

声明只是在栈中创建了对定义在堆中数据的引用

注:该理解只是我的个人理解,类比JVM的一种猜测

总结

项目中引用的lib只是一个方法的集合,若需要使用这些方法需要先声明一下。

就好比一个餐馆,lib就相当于是厨师会做的菜,方法声明就相当于菜单,有时,菜单并不会将厨师会的所有菜品都列上,仅仅列出需要卖的就行。

但是,作为一个顾客,如果没有菜单只有厨师,我又不知道餐馆能做什么菜。如果只有菜单没有厨子(只有声明没有真实引入lib),就算我点了某个菜也是做不出来的。

Leave a Comment