我的头文件中应该包含什么C++
What Should go in my Header File in C++?
我刚刚开始我的第一个C++程序,几乎只是边走边学。该程序应该有 3 个不同的文件,一个头文件 (prog1.h(,一个 prog1.cpp 文件(不确定这个的正确术语(和一个包含 main: 测试我们的程序 (prog1_test.cpp( 的测试文件。
没有就任何方面寻求帮助(然而,我相信一旦我进入它,我会发布另一个问题(,但认为你需要知道程序应该做什么才能理解我的问题。我们的程序应该从文件中读取一些数字,并将这些数字放入 2D 数组中。然后,它应该为每个数字值分配字符,并打印当前数组和用字符创建的"图片"。然后它将遍历数组,确保每个数字的值与它的邻居相差不超过 1,如果是这样,程序将用其相邻值的平均值替换该数字。然后,程序将打印出此校正后的数组和"图片",这些字符分配给校正后的数组。
我知道头文件应该包含将跨多个文件使用的代码,但是我无法弄清楚我的程序的哪些部分需要进入此文件。例如,我的用于打开、读取和关闭数据文件的代码是否包含在此处,或者由于文件只被打开、读取和关闭一次,因此是否包含?
头文件包含函数和类声明。这些只是声明函数的名称、返回类型和参数列表。.cpp文件包含这些函数的定义 - 即实际实现。如果在其他文件中#include
头文件,则头文件对程序的其余部分可见,但实现详细信息隐藏在.cpp文件中。
.cpp文件中声明/定义的任何不在 .h 文件中的内容对程序的其余部分都不可见,因此您可以在.cpp文件中定义内部变量、帮助程序函数等,而这些实现细节将不可见。下面的例子foo()
程序的粗略草图如下所示:
在 prog1.h 中:
#include <iostream> // and whatever other libraries you need to include
#define ARRAY_SIZE 100 // and other defines
// Function declarations
// Read number from file, return int
void read_number(int array[ARRAY_SIZE][ARRAY_SIZE]);
char assign_char(int n);
void print_array(int array[ARRAY_SIZE][ARRAY_SIZE]);
void neighbor_check(int array[ARRAY_SIZE][ARRAY_SIZE]);
在 prog1.cpp:
// included headers, defines, and functions declared in prog1.h are visible
#include "prog1.h"
void read_number(int array[ARRAY_SIZE][ARRAY_SIZE]) {
// implementation here
}
char assign_char(int n) {
char c;
// implementation here
return c;
}
void print_array(int array[ARRAY_SIZE][ARRAY_SIZE]) {
// implementation here
}
void neighbor_check(int array[ARRAY_SIZE][ARRAY_SIZE]) {
// implementation here
}
// not visible to anything that #includes prog1.h
// since it is not declared in prog1.h
void foo() {
// implementation here
}
在prog1_test.cpp:
// included headers, defines, and functions declared in prog1.h are visible
#include "prog1.h"
// any other includes needed by main()
int main() {
int array[ARRAY_SIZE][ARRAY_SIZE];
read_number(array);
for (int i = 0; i < ARRAY_SIZE; i++) {
for (int j = 0; j < ARRAY_SIZE; j++) {
assign_char(array[i][j]);
}
}
neighbor_check(array);
print_array(array);
return 0;
}
使用各种头文件以及与应用程序文件分开的代码/实现文件是为了促进代码的可维护性和重用。通过将所有相关函数、变量和数据结构收集在一个文件中,我们避免了在我们编写的每个后续应用程序中复制该代码。
以您的情况为例,您将开发与矩阵或数组相关的例程。此方案允许您将处理数组的常见例程收集到单个文件中,例如arrays.c
。现在,无论您再编写多少个程序,您都有一个包含数组例程的通用文件。现在,如果您再编写 5 个需要数组例程的应用程序,您就可以将它们放入arrays.c
中。
为了可维护性,假设您现在有了一种更有效的方式来处理从文件到数组的输入。您不必返回并更新 5 个不同应用程序文件中的 read_array
函数,只需在 arrays.c
中更新一个read_array
函数,您就完成了为使用它的所有应用程序更新该例程。
header
文件如何适应?为了在其他应用程序中使用数组函数,应用程序需要一种包含代码的通用方法,以使其可供使用。这是通过在需要它的每个应用程序中包含arrays.h
头文件来完成的。好的,那么arrays.h
什么进去,什么进arrays.c
?头文件将包含实现 arrays.c
中包含的function definitions
所必需的数组例程header files, function declarations, data structures and variables
。这样,任何希望使用数组例程的应用程序只需在其文件开头包含行#include "arrays.h"
即可访问包含在arrays.c
中的数组函数
一个例子(在C中(将有助于解决问题。假设您有几个数组函数,这些函数将文本文件中的行读取为字符串read_array
,prn_array
打印行,然后释放数组和字符串free_array
使用的内存。您已在 array.c
中收集了数组函数。(我们知道我们会在顶部包含array.h
。因此,例如:
#include "array.h"
char **read_array (char *filename)
{
char *buffer = NULL;
size_t len = 0;
ssize_t read;
char **array = NULL;
int cnt = 0;
FILE *fp;
fp = fopen (filename, "r"); //open file , read only
if (!fp) {
fprintf (stderr, "failed to open file for readingn");
return NULL;
}
array = calloc (AMAX, sizeof (*array) * AMAX); /* allocate pointers, set NULL */
while ((read = getline (&buffer, &len, fp)) != -1) { /* read each line */
if (cnt == AMAX) {
fprintf (stderr, "Error: AMAX reachedn");
break;
/* you will realloc *array here in real life */
}
if (buffer[read-1] == 'n') { /* strip newline */
buffer[read-1] = 0;
read -= 1;
}
array[cnt] = strdup (buffer); /* copy buffer to array[cnt] */
cnt++; /* increment counter */
}
fclose (fp); /* close file stream (fp) */
return array;
}
void prn_array (char **array)
{
register int j = 0;
while (array[j]) {
printf (" array[%d]: %sn", j, array[j]);
j++;
}
}
void free_array (char **array)
{
register int j = 0;
while (array[j]) { /* for each allocated string */
free (array[j]); /* free pointer to string */
j++;
}
free (array); /* free array */
}
现在让我们创建我们的标头。我们收集我们的function declarations
以及使用的任何variables
或data structures
,还包括我们的职能所需的system headers
和任何其他included header files
array.h
:
#ifndef MY_ARRAY_H
#define MY_ARRAY_H 1
/* headers required for array.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define AMAX 100
/* function declaration */
char **read_array (char *filename);
void prn_array (char **array);
void free_array (char **array);
#endif /* MY_ARRAY_H */
请注意,我们已经将标头的内容包装在一个测试#ifndef MY_ARRAY_H
中,该测试只是询问编译器是否定义了MY_ARRAY_H
,ifndef
(如果尚未定义(,我们让编译器知道#define
之后的所有内容,直到我们到达我们定义为MY_ARRAY_H
的 if 语句#endif
末尾,以便如果另一个文件尝试包含相同的标头 - 编译器已经知道它拥有它,不需要再次包含它。(不是必需的,但我们也给出了我们对MY_ARRAY_H
的定义值1
那么我们如何将自定义标头array.h
和用于处理数组的自定义函数放入arrays.c
为我们工作呢?我们编写一个应用程序,该应用程序使用 arrays.c
中的函数,并在应用程序中声明arrays.c
中的所有函数,我们只需在应用程序中包含array.h
。(下面称为application.c
(:
#include <stdio.h>
#include "array.h" /* include array.h */
int main (int argc, char *argv[]) {
if (argc < 2) {
printf ("filename.csv please...n");
return 1;
}
char **my_array = NULL; /* declare pointers */
my_array = read_array (argv[1]); /* call read_array */
prn_array (my_array); /* call prn_array */
free_array (my_array); /* call free_array */
return 0;
}
编译 application.c 和 array.c 文件:
gcc -Wall -Wextra -o application application.c array.c
在任何短文本文件(少于 100 行(上运行它
$ ./application input.txt
array[0]: 1. This is a simple input file with line numbers
array[1]: 2. for use with application showing the use of
array[2]: 3. header file: array.h
array[3]: 4. array functions defined in: array.c
array[4]: 5. (blank)
array[5]: 6. compiled with the following:
array[6]: 7. gcc -Wall -Wextra -o application application.c array.c
array[7]: 8. --------
array[8]: 9. Now you know!
现在,您可以看到创建一个单独的文件,其中包含我们将使用的相关函数,变量和数据结构以及创建头文件的好处。我们可以在喜欢的任何应用程序中重用该代码,只需将头文件arrays.h
包含在我们的应用程序中即可。我们可以在一个地方更新和维护所有数组函数,更新我们的arrays.c
将更新使用该代码的所有其他应用程序。
我知道我遗漏了很多,但请确保您对这些概念持扎实态度。它们是处理多个源文件的基础,并包含在 C/C++ 中。
以下基本内容应出现在头文件中。
- 带函数声明、数据变量、构造函数的类体和析构函数声明。
- 声明所有函数.class。 注意:不是函数体或定义。
- 内嵌功能。
- 定义
- 所有库都包含头文件。所以你只需要在你各自的.c文件中添加一个头文件。头文件。
- 结构
- IFNDEF 块
- 前瞻申报如果你需要它,有时。
- Doxygen 评论函数、类和变量。
- 此文件的描述为在 doxygen 的头文件顶部注释。等。。。
头文件不应包含任何代码。
- c++库的公共头文件中应该包含什么
- 在C++中包含原型文件的正确方法是什么?
- 我应该包含什么来制作 boost.python 扩展?
- 在Visual Studio C++项目中包含源库的正确方法是什么?
- 在使用包含冒号的类似函数的宏时,是什么导致了这种编译器差异?
- 读取大文件(>2GB)(文本文件包含以太网数据)并通过不同参数随机访问数据的最佳方法是什么?
- 在wxWidgets的事件中包含我自己的数据的最佳方法是什么?
- 是否可以将要"ShellExecute"的文件包含在 dll 中?如果是这样,"ShellExecute"中的文件位置应该是什么?
- 为什么我应该在scanf()-家族成员中包含一个长度修饰符作为参数?有什么好处?使用长度修改器进行扫描的作用
- 什么是正确的 macOS vscode 智能感知C++包含标准库的路径?
- C++ LibcURL IMAP 获取包含主题行的变量是什么?
- VS2015 / 2017中的TRACE宏无法编译 - 我需要包含什么?
- (C++)我需要在新类的头文件中包含什么
- 我可以在c++接口(抽象类)中包含什么
- 接口的帮助字符串应包含什么
- 指针包含什么类型的数据
- 我的头文件中应该包含什么C++
- cv::meanShift函数包含什么
- 依赖于另一个静态库的静态库包含什么?
- 空字符串在C++中包含什么