【问题标题】:Linker Error when separating code into .h and .cpp files将代码分离为 .h 和 .cpp 文件时出现链接器错误
【发布时间】:2010-07-16 21:34:13
【问题描述】:

我有一个用 c++ 打印出枚举值的实现

如果我将所有代码放在一个 .h 文件中,一切都会运行良好。如果我将函数实现分离到 .cpp 文件中,则会出现链接器错误。

这是我的主文件

#include <iostream>
#include <vector>
#include "Day.h"
using namespace std;

int main(){
    initializeDayNames();
    Day a = Clubs;
    cout << a;
}

这是.h文件

#ifndef __Day__
#define __Day__

#include <iostream>
#include <vector>
#include <string>
using namespace std;

enum Day {Clubs, Hearts, Diamonds, Spades} ;

vector<string> DayNames = vector<string>();

ostream & operator<<(ostream & out, Day cs);

void initializeDayNames();

#endif

和 .cpp 文件

#include <iostream>
#include "Day.h"
#include<string>
#include<vector>
using namespace std;

void initializeDayNames(){
    DayNames.push_back("Clubs");
    DayNames.push_back("Hearts");
    DayNames.push_back("Diamonds");
    DayNames.push_back("Spades");
}


ostream & operator<<(ostream & out, Day cs){
    out << DayNames[cs];
    return out;
}

我做错了什么

具体错误是

Error   1   error LNK2005: "class std::vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > DayNames" (?DayNames@@3V?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@std@@A) already defined in Day.obj main.obj

Error   2 fatal error LNK1169: one or more multiply defined symbols found   

【问题讨论】:

  • 你只是从不同的枚举示例中挑选部分吗?我想查看以不同卡片套装命名的每周 4 天的日历。
  • 创建一个原型代码生成器,里面有很多硬编码的东西
  • 请不要在头文件中使用using namespace std; 行,而是使用std:: 限定符(请参阅本文中的第一个答案:stackoverflow.com/questions/1265039/using-std-namespace
  • 更喜欢使用不带下划线的包含守卫和标识符。前导下划线保留用于编译器和实现。您的标识符和包含保护可能与当前或未来版本的编译器冲突。
  • 另请注意:使用 Day 是个坏主意。所有包含双下划线的标识符都由编译器或操作系统保留,您可能会与stackoverflow.com/questions/228783/… 发生冲突

标签: c++ linker-errors


【解决方案1】:

你正在初始化两个副本

vector<string> DayNames = vector<string>();

因为你包含了两次标题。

你应该把它替换为

extern vector<string> DayNames;

在h文件中和

vector<string> DayNames = vector<string>();

在 cpp 文件中。

另外你好像有两份

ostream & operator<<(ostream & out, Day cs);

您的标头保护对这种情况没有帮助的原因是,当您包含标头时,您基本上会在您包含标头的所有文件中复制定义。

在 C 中,当你声明一个变量时,你基本上是实例化它/为它分配静态空间。当您将变量声明放在标头中时,您实际上所做的是在两个不同的对象中为变量分配静态存储空间,从而产生错误。

【讨论】:

  • 修复了ostream重复部分。
  • 编译还有问题吗?我还没有将它放入编译器,所以我不确定这是否是所有问题:)
  • #ifndef 声明是否应该防止标题中的内容被声明两次??
  • 它适用于外部的东西,但我有点困惑为什么 #ifndef 部分没有帮助它被包含两次
  • 不,ifndef 是为了防止标头中的内容在同一个文件中被声明两次,但是当您在两个不同的文件中包含标头时,内容会重复(这就是为什么您通常应该只在 .h 文件中编写函数头和内容)。
【解决方案2】:

您在 DayNames 声明中缺少 extern

【讨论】:

    猜你喜欢
    • 2021-04-03
    • 2011-05-12
    • 2022-06-11
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    相关资源
    最近更新 更多