我的头文件中应该包含什么C++

What Should go in my Header File in C++?

本文关键字:包含 什么 C++ 文件 我的      更新时间:2023-10-16

我刚刚开始我的第一个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_arrayprn_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以及使用的任何variablesdata 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_Hifndef(如果尚未定义(,我们让编译器知道#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++ 中。

以下基本内容应出现在头文件中。

  1. 带函数声明、数据变量、构造函数的类体和析构函数声明。
  2. 声明所有函数.class。 注意:不是函数体或定义。
  3. 内嵌功能。
  4. 定义
  5. 所有库都包含头文件。所以你只需要在你各自的.c文件中添加一个头文件。头文件。
  6. 结构
  7. IFNDEF 块
  8. 前瞻申报如果你需要它,有时。
  9. Doxygen 评论函数、类和变量。
  10. 此文件的描述为在 doxygen 的头文件顶部注释。等。。。

头文件不应包含任何代码。