当我声明ifstream时,为什么会出现“已经定义”的错误?

时间:2013-01-25 05:51:32

标签: c++ visual-studio-2010 linker-errors

我是新手使用头文件等等,上学期我们在一个巨大的(可怕的:p)文件中做了所有事情......

我做了一些我不应该做的事吗?尝试运行该程序会导致以下结果:

1>  LINK : ~~~\CSC 161\Accounting Assignment\Debug\Accounting Assignment.exe not found or not built by the last incremental link; performing full link
1>driver.obj : error LNK2005: "class std::basic_ifstream<char,struct std::char_traits<char> > welcomeFile" (?welcomeFile@@3V?$basic_ifstream@DU?$char_traits@D@std@@@std@@A) already defined in statistics.obj
1>~~~~\CSC 161\Accounting Assignment\Debug\Accounting Assignment.exe : fatal error LNK1169: one or more multiply defined symbols found
1>

statistics.h:

#ifndef _STATISTICS_INTERFACE_
#define _STATISTICS_INTERFACE_
...
#include<fstream>

using namespace std;
ifstream  welcomeFile;   //if I comment this out, it compiles

class Stats
{
...blah...
};

void welcome();
void pause();
void printFile(ifstream &inFile);

#endif

statistics.cpp:

#include "statistics.h"

...working functions...

void welcome()
{
    system("CLS");
    welcomeFile.open("about.txt");
    printFile(welcomeFile);
    welcomeFile.close();
    pause();
}

错误看起来像某个东西试图被定义两次,但我认为#ifndef应该设置它所以它只定义了一些东西,如果它们还没有?这是我宣布welcomeFile的唯一地方......

2 个答案:

答案 0 :(得分:6)

因为您在头文件中定义了对象并违反了一个定义规则

永远不要在头文件中定义对象!

标题保护会阻止标题内容多次包含在 相同 translation unit 在预处理期间。它们不会阻止内容包含在不同的翻译单元中。当您将此头文件包含在不同的翻译单元中时,每个单元都将具有此对象的定义 编译器分别编译每个翻译单元以生成单独的目标文件( .o ),每个.o文件都将具有此对象定义的副本。当链接器在生成.exe时尝试链接到对象/符号名称时,它会找到同一对象/符号的多个定义,从而导致混淆哪个链接到哪个。为避免此问题,标准定义了一个称为 One defintion rule(ODR) 的规则,该规则禁止同一实体的多个定义。
如您所见,在头文件中包含对象定义,并且在多个翻译单元中包含该头文件会违反ODR。

如果要使用全局对象,则需要将其声明为extern并在一个且只有一个源文件中定义它。

好读:
error LNK2005, already defined?

答案 1 :(得分:2)

您应该将该定义放在.cpp文件中。否则,包含此.h文件的每个文件都将具有此变量的定义,该变量在链接期间最终会发生冲突。

P.S。将using namespace std;放入标题is considered bad