如何创建像标准库头一样的头,以便在不链接头中函数的所有对象文件的情况下编译程序?

How to create a header like a standard library header, so that program can be compiled without linking all object files of functions in the header?

本文关键字:函数 链接 对象 编译程序 情况下 文件 标准 创建 何创建 一样      更新时间:2023-10-16

>我试图创建一个可以包含的头文件,例如
#include "sort.h "和包含标头的程序可以正常
编译g++ main.cpp
而无需将标头中函数的每个对象文件与 main 链接。

g++ -c main.cpp insertion_sort.cpp merge_sort.cpp

g++ main.o merge_sort.o insertion_sort.o

所以我必须为标头中的每个函数链接每个对象文件。还是他们的另一种方式?
头文件:

//sort.h file
#ifndef sort_h
#define sort_h
void insertion_sort(int *a,int n);
void merge_sort(int *a,int n);
//I want to include more functions
#endif

如何像cmath或stdlib.h这样的普通标题一样使用我的标题?

您似乎觉得从标准库标头中获得的内容没有需要链接的相应对象文件/库文件。这是错误的。

标准库链接到您的应用程序,只是编译器会自动为您完成。您不必手动告诉它这样做。

您的应用程序还需要可用的标准库才能运行。这就是为什么您必须在要运行使用 Visual Studio 构建的程序的计算机上安装 Microsoft 可再发行组件的原因。其他编译器也有类似的要求,您需要将其运行时库与应用程序一起分发。

简而言之,标准库与其他库没有什么不同,除了编译器在幕后为您链接它。

您可以编写完全由头文件组成的模板函数。然后,您不需要任何.cpp文件,也不需要链接到目标文件。虽然这不是对所问问题的直接解决方案,但它是一种"不为每个函数链接每个对象文件"的方法。

把所有东西放在一起

如果我们举个例子,您可以尝试更改您的 sort.h 文件,如下所示

//sort.h file
#ifndef sort_h
#define sort_h
template <typename T>
void insertion_sort(T* a,int n) {
// insertion sort implementation goes here
}
template <typename T>
void merge_sort(T* a,int n) {
// merge sort implementation goes here
}
#endif

在此处将排序例程编写为模板函数时,函数必须足够泛型以适应泛型 T 类型。通常,对于排序例程,T 必须小于可比性。

单独的接口和实现

如果你不喜欢把文档、接口和实现都放在一个地方,你可以先声明函数和它的文档。然后,您可以在下面或可能在其他文件中定义它。因此,也可以执行以下操作:

//sort.h file
#ifndef sort_h
#define sort_h
/**
*  Function documentation
*/
template <typename T>
void insertion_sort(T* a,int n);
/**
*  Function documentation
*/
template <typename T>
void merge_sort(T* a,int n);

#include "insertion_sort.h"
#include "merge_sort.h"
#endif

//insertion_sort.h file
#ifndef insertion_sort_h
#define insertion_sort_h
template <typename T>
void insertion_sort(T* a, int n) {
// insertion sort implementation goes here
}
#endif

//merge_sort.h file
#ifndef merge_sort_h
#define merge_sort_h
template <typename T>
void merge_sort(T* a, int n) {
// merge sort implementation goes here
}
#endif

有些人喜欢将模板头实现文件称为.tpp文件。这取决于您的偏好。

使用从主.cpp

您可以使用 main 中的第一个或第二个选项.cpp如下所示:

//main.cpp
#include "sort.h"
#include <vector>
int main() {
std::vector<int> vec_int;
// fill vector
insertion_sort(&vec_int[0], vec_int.size());
std::vector<double> vec_double;
// fill vector
merge_sort(&vec_double[0], vec_double.size());
}

编译

由于我们没有使用任何 cpp 文件,现在编译 main.cpp 应该像

g++ -Wall -Wextra -g main.cpp

假设 main.cpp 和我们的头文件位于同一目录中。如果头文件在某个名为 include 的目录中,那么我们编译

g++ -Wall -Wextra -g -Iinclude main.cpp