textFileRead的多重定义(char *)

时间:2012-11-25 17:58:16

标签: c++ definition

我正在使用此头文件来读取文本文件(我用它来加载着色器文件),我在两个不同的类中使用它。

我收到错误textFileRead(char *)的多重定义。

这是头文件:

#ifndef READFILE_H
#define READFILE_H

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "string"
#include "fstream"

char *textFileRead(char *fn) {

FILE *fp;
char *content = NULL;

int count=0;

if (fn != NULL) {
    fp = fopen(fn,"rt");

    if (fp != NULL) {

  fseek(fp, 0, SEEK_END);
  count = ftell(fp);
  rewind(fp);

        if (count > 0) {
            content = (char *)malloc(sizeof(char) * (count+1));
            count = fread(content,sizeof(char),count,fp);
            content[count] = '\0';
        }
        fclose(fp);
    }
}
return content;
}


#endif READFILE_H

我做错了什么?

3 个答案:

答案 0 :(得分:0)

您需要确保头文件中的代码仅包含在每个编译单元中一次。为此,您将其放在文件的开头:

#ifndef READFILE_H
#define READFILE_H

最后:

#endif

当然,标识符READFILE_H对于每个文件应该是唯一的。接下来要做的是:只在头中保留函数和类的声明,实现应该存在于单独的实现文件(.c或.cpp或.cc)中。因此,在您的标题中,您将仅声明您的函数:

char *textFileRead(char *);

,你的函数定义将在一个单独的.c文件中。

答案 1 :(得分:0)

标题中定义的函数需要标记为inline以防止多重定义。

这个,或者将实现分离到实现文件。

在同一翻译单元中包含防范多重定义的警卫,这是一个链接器问题。该符号在翻译单元中定义了多次。

答案 2 :(得分:0)

您正在头文件中定义该函数,这意味着编译器将在包含此标头的每个源文件中复制相同的函数。在链接目标文件时,链接器将不知道要使用哪个版本。 (它不能知道它们是相同的,只是它们的签名是相同的。)

解决此问题的一种方法是将实现移动到源文件,并将声明保留在头文件中,如下所示:

<强> readfile.h

#ifndef READFILE_H
#define READFILE_H

char *textFileRead(char *fn);

#endif

<强> readfile.cpp

#include "readfile.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <fstream>

char *textFileRead(char *fn) 
{
    FILE *fp;
    char *content = NULL;
    int count=0;

    /* ... code ... */

    return content;
}

另一种解决方案是标记函数inline并将实现保留在头文件中。像这样:

#ifndef READFILE_H
#define READFILE_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <fstream>

inline char *textFileRead(char *fn) 
{
    FILE *fp;
    char *content = NULL;

    /* ... code ... */

    return content;
}

在最后一种情况下,编译器可以选择内联调用它的函数,而不是生成对它的调用。

在上面的示例中,也可以使用static代替inline,或者在匿名命名空间中包含定义。但是,建议不要使用这些方法。除非您有特定的理由想要在函数头文件中内联函数并使其正文可用,否则我会选择第一种方法。