C ++中的头文件应该包含哪些内容?

时间:2014-09-10 04:32:52

标签: c++ header-files

我刚开始学习我的第一个C ++课程,而且我正在学习。该程序应该有3个不同的文件,一个头文件(prog1.h),一个prog1.cpp文件(不确定这个的正确术语)和一个包含main的测试文件:测试我们的程序(prog1_test.cpp) )。

不要求任何帮助(但是,我确定在我进入之后我会发布另一个问题),但是你想知道这个程序是什么应该这样做是为了理解我的问题。我们的程序应该从文件中读取一些数字并将这些数字放入2D数组中。然后它应该为每个数字值分配字符并打印当前数组和"图片"用角色创建。然后它将通过数组,确保每个数字的值与它的邻居的值不超过1,如果是,则程序将用其相邻的平均数替换该数字。值。然后程序将打印出这个校正过的数组和"图片"使用分配给更正数组的字符创建。

我知道头文件应该包含将在多个文件中使用的代码,但我很难弄清楚我的程序的哪些部分需要在这个文件中。例如,我的代码打开,读取和关闭数据文件是否包括在这里,或者没有,因为文件只被打开,读取和关闭一次?

3 个答案:

答案 0 :(得分:6)

头文件包含函数和类声明。这些只是声明函数的名称,返回类型和参数列表。 .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;
}

答案 1 :(得分:3)

使用各种头文件,以及与应用程序文件分开的代码/实现文件,以促进代码的可维护性和重用。通过在单个文件中收集所有相关的函数,变量和数据结构,我们可以防止在我们编写的每个后续应用程序中复制该代码。

以您的情况为例,您将开发与矩阵或数组相关的例程。此方案允许您将处理数组的常用例程收集到单个文件中,例如arrays.c。现在,无论您编写多少程序,都有一个包含数组例程的公共文件。现在,如果你再编写5个需要你的数组例程的应用程序,你可以准备好进入arrays.c

为了可维护性,假设您现在有一种更有效的方法来处理从文件到阵列的输入。您无需返回并更新5个不同应​​用程序文件中的read_array函数,只需更新read_array中的一个arrays.c函数,即可完成所有应用程序的更新例程。用它。

header文件如何适应?为了在其他应用程序中使用您的数组函数,应用程序需要一种通用的方法来包含代码以使其可供使用。这是通过在每个需要它的应用程序中包含arrays.h头文件来完成的。好的,那么arrays.h中的内容以及arrays.c中的内容是什么?您的标头文件将包含实现header files, function declarations, data structures and variables中包含的function definitions所需的数组例程的arrays.c。这样,任何希望成为数组例程用户的应用程序只需在其文件开头包含行#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 reading\n");
        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 reached\n");
            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]: %s\n", 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之后的所有内容,直到我们到达#endif的if语句MY_ARRAY_H的末尾,这样如果另一个文件试图包含相同的标题 - 编译器知道它已经拥有它并且不需要再次包含它。 (不是必需的,但我们也会定义MY_ARRAY_H1

那么我们如何将自定义标头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 ++中。

答案 2 :(得分:1)

以下基本内容应出现在您的标题文件中。

  1. 具有函数声明,数据变量,构造函数的类体 和析构函数声明。
  2. 声明所有功能 类。注意:不是函数体或定义。
  3. 内联 功能。
  4. define
  5. 所有库都包含头文件。那么你 需要在你自己的.c文件中只添加一个头文件 头文件。
  6. 结构
  7. ifndef block
  8. 前言宣言 如果你需要它一些课程。
  9. doxygen评论 函数,类和变量。
  10. 此文件的描述为 在doxygen的头文件中发表评论。 等...
  11. 标题文件不应包含任何代码。

相关问题