【问题标题】:fatal error multiply defined symbols found发现致命错误多定义符号
【发布时间】:2013-08-20 14:45:47
【问题描述】:

我收到了这个错误,但我不明白,因为“int const ITEMS”从未像下面错误中所说的那样在 DisplayErrorMessage.cpp 中声明......任何帮助。

1>Main.obj : error LNK2005: "int const ITEMS" (?ITEMS@@3HB) already defined in DisplayErrorMessage.obj
1>MakeSelection.obj : error LNK2005: "int const ITEMS" (?ITEMS@@3HB) already defined in DisplayErrorMessage.obj
1>ShowMenu.obj : error LNK2005: "int const ITEMS" (?ITEMS@@3HB) already defined in DisplayErrorMessage.obj
1>c:\users\kanaan\documents\visual studio 2010\Projects\Assign2\Debug\Assign2.exe : fatal error LNK1169: one or more multiply defined symbols found

代码如下:

头文件

#ifndef _VENDINGMACHINE_H_
#define _VENDINGMACHINE_H_

#include <iostream>
#include <cmath>
#include <string>

using namespace std;

  //extern int Denominations;
  extern int const ITEMS = 9;

  extern int Coins[5];
  extern int NumCoins[5]; //assume we have 10 coins of each denomination

   extern int ItemPrice[ITEMS ]; //price in cents
   extern int NumItems[ITEMS]; 


//extern double Total_Price;
//extern double Item_Total;

class VendingMachine{
public:
    void MakeSelection();
    int ReturnChange(int change, int Coins[], int NumCoins[]);
    void ShowMenu();
    void DisplayErrorMessage(int error);
    void PrintConfidentialInformation(int Denominations, int Items, int Coins[], 
                                                    int NumCoins[], int ItemPrice[] , int NumItems[]);

private:
    int selection;
    string code;
    double Each_Item[ITEMS];       //price for each item
};
#endif //_VENDING_MACHINE_H_

cpp 文件如下。 使选择.cpp #include "自动售货机.h"

void VendingMachine::MakeSelection(){



   //assume we have 10 coins of each denomination

  double Total_Price;
// double Item_Total;

  int Coins[5] = {100, 50, 20, 10, 5};
   int NumCoins[5] = {10, 10, 10, 10, 10}; 
    int ItemPrice[ITEMS] = { 75, 120, 120, 100, 150, 95, 110, 50, 120 }; //price in cents
  int NumItems[ ITEMS] = { 10, 10, 10, 10, 10, 10, 10, 10, 10 };

    string Product[ITEMS] = {"Water","Coke","Diet Coke","Iced Tea","Swiss Chocolate","Candy",
                                                    "Chips","Bubble Gum","Turkish Delight"};
    int b = 0;
int a = 1;

cout << "Please enter the number of your choice from the menu above. " << endl;

do{
    cout << "\nEnter the number of product OR End transaction: " << endl;
    cin >> selection;
    cout << "\nYou have selected " <<Product[selection] << endl;

    if(selection >= 1 && selection <= 9){

        NumItems[selection - 1] = NumItems[selection - 1] - 1;

        if(NumItems[selection - 1] >= 0)
            Total_Price = Total_Price + ItemPrice[selection - 1];

        else{
            int error = 1;
            DisplayErrorMessage(error);         //Item finised
            cout <<selection<< endl;
        }
    }
    else if(selection == 10)
        cout << "\nTransaction Ended" << endl;

    else if(selection == 99){

        cout << "Enter the code to access maintanance: " <<endl;
        cin >> code;

        while(code != "111"){
            int error = 2;
            DisplayErrorMessage(error);
            cin >> code;
        }

        cout << endl;
        cout << "\t\t\t\t\tSales Report " << endl;
        cout << "==================================================== " << endl;
        cout << endl;
        cout << "Number of each product sold with Income cost: " << endl;
        cout << endl;

        do{
            if(NumItems[b] >= 0){

                Each_Item[b] = Each_Item[b] + ItemPrice[b];

                cout << NumItems[b] << "" << Product[b] << " sold for the total cost of " <<(10 - NumItems [b]) * Each_Item[b]/ 100 <<endl;   

                Total_Price = Total_Price + ((10 - NumItems[b]) * Each_Item[b]/100);
            }
            b++;
        }while(a <= ITEMS);
    }
    else{ 
        int error = 3;
        DisplayErrorMessage(error);
    }
}while(selection != 10);
}

DisplayErrorMessage.cpp

#include "Vending Machine.h"

void VendingMachine::DisplayErrorMessage(int error){

if (error == 1){
    cout << "\nSorry we are run out of item number ";
}
else if (error == 2){
    cout << "\nInvalid selection - Please re-select your choice" << endl;
}
else if (error == 3){
    cout << "\nIncorrect Password - Please re-enter" << endl;
}
else
    cout << "\nNot enough fund" << endl;
}

请帮忙。

【问题讨论】:

  • 我打赌你在某个头文件中声明了它(并且不小心定义了它)。
  • 包括警卫可能会帮助你
  • 可能只是一个不使用pragma one的包含...
  • @SpongeBobFan:不是当前情况,那是链接错误,不是编译错误。
  • @Trinimon, pragma once,但它不是 100% 可移植的,因为它不是 c++ 标准的一部分,但是我不知道有任何现代编译器无法处理它

标签: c++


【解决方案1】:

你的问题

extern int const ITEMS = 9;

标记这个extern 是正确的,但是你继续给它一个定义,取消了所有可爱的正确性。

当您在标题中定义符号时,无论您是否使用包含保护,当您的翻译单元链接在一起时,您将得到多个定义错误。

您必须在精确的一个翻译单元中定义符号ITEMS——这通常意味着在“源”文件中定义它,而不是头文件。


天真的修复

所以,在你的标题中:

extern int const ITEMS;  // definition found elsewhere

然后,在一个.cpp文件中:

int const ITEMS = 9;

真正的修复

但是,哎呀!您需要在标题中使用此常量,因为某些数组大小依赖它。

因此,您不必在程序中的所有翻译单元之间创建一个符号ITEMS,而是必须有一个每个翻译单元的本地定义。为此,我们使用static 关键字将符号文件设为静态。

所以,在你的标题中:

static int const ITEMS = 9;  // visible only in this TU

现在,多个翻译单元(松散地说,这意味着使用此标头的每个 .cpp)都将拥有自己的 ITEMS 版本,就像以前一样......但这一次,因为它们被标记为 static ,每个都是该翻译单元的本地,因此它们不会在链接时发生冲突。

【讨论】:

    【解决方案2】:

    首先,在您的标头Vending Machine.h 中(顺便说一句,在文件名中包含空格是个坏主意,为什么不直接将其命名为VendingMachine.h?),以下行:

      extern int const ITEMS = 9;
    

    是一个定义,而不是一个声明,尽管extern,因为初始化部分(“= 9”)。

    现在,这个标头包含在多个源文件 (.cpp) 中,并且ITEMS 具有外部链接(明显是因为 extern),导致每个源文件 (re)定义相同 ITEMS,因此会出现多重定义错误。

    如果您将行更改为

      static int const ITEMS = 9;
    

    或者干脆

      int const ITEMS = 9;
    

    (实际上是等效的,因为const 全局变量的特定规则),那么每个ITEMS(在每个源文件中)都将具有内部链接,这一切都很好。


    编辑:此外,以下答案很好地解释了extern(“外部链接”和“声明,未定义”)的两个含义:https://stackoverflow.com/a/2840401

    编辑:另外两个关于extern(添加“静态存储持续时间”的含义)的好答案:https://stackoverflow.com/a/3994572https://stackoverflow.com/a/18450398

    【讨论】:

      【解决方案3】:
        extern int const ITEMS = 9;
      

      因为你包含了一个初始化器,这个声明也是一个定义。并且由于您声明它extern,所以只有一个对象ITEMS。但是有了头文件中的那一行,包含头文件的所有内容都有自己的定义。

      您可以省略extern,在这种情况下const 将暗示static

        int const ITEMS = 9;
      

      那么ITEMS 在每个编译单元中都是一个不同的对象,但是如果你总是将它用作一个值并且从不对它的地址做任何事情,这并不重要。

      或者,如果您启用了 C++11 支持,您可以:

        constexpr int ITEMS = 9;
      

      ...它告诉编译器将ITEMS 对象与inline 函数类似地处理,并且可以多次定义。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-21
        • 2011-12-07
        • 2021-12-15
        • 2011-07-19
        相关资源
        最近更新 更多