Kaka Awira
Kaka Awira

Reputation: 25

fatal error multiply defined symbols found

I got this error but I don't understand it because "int const ITEMS" was never declared in DisplayErrorMessage.cpp like what it said in the error below..Any help.

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

Here is the code:

Header file

#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_

The cpp files are as follows. MakeSelection.cpp #include "Vending Machine.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;
}

Help pliz.

Upvotes: 2

Views: 3892

Answers (3)

gx_
gx_

Reputation: 4770

First, in your header Vending Machine.h (by the way, it's a bad idea to have spaces in file names, why don't you just name it VendingMachine.h?), the following line:

  extern int const ITEMS = 9;

is a definition, not a declaration, despite the extern, because of the initializer part (the "= 9").

Now, this header is included by multiple source (.cpp) files, and ITEMS has external linkage (explicitly because of extern), resulting in each source file (re)defining the same ITEMS, hence the multiple definition error you get.

If you change the line to

  static int const ITEMS = 9;

or simply

  int const ITEMS = 9;

(which is actually equivalent because of the particular rules for const globals), then each ITEMS (in each source file) will have internal linkage and that will be all fine.


Edit: Additionally, the following answer is a nice explanation of the two meanings of extern ("external linkage" and "declare, not define"): https://stackoverflow.com/a/2840401

Edit: Two other good answers about extern (which add the meaning of "static storage duration"): https://stackoverflow.com/a/3994572 and https://stackoverflow.com/a/18450398

Upvotes: 5

aschepler
aschepler

Reputation: 72463

  extern int const ITEMS = 9;

Since you include an initializer, this declaration is also a definition. And since you declare it extern, there is only one object ITEMS. But with that line in the header file, everything that includes the header makes its own definition.

You could leave off the extern, in which case the const will imply static.

  int const ITEMS = 9;

Then ITEMS is a different object in each compilation unit, but that doesn't matter much if you always use it as a value, and never do anything with its address.

Or if you have C++11 support enabled, you could have:

  constexpr int ITEMS = 9;

... which tells the compiler to treat the one ITEMS object similarly to an inline function, and it can be defined more than once.

Upvotes: 3

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385365

Your problem

extern int const ITEMS = 9;

Marking this extern is correct, but then you went ahead and gave it a definition, undoing all that lovely correctness.

When you define symbols in headers, whether you're using include guards or not, when your translation units are linked together you will get multiple definition errors.

You must define the symbol ITEMS in precisely one translation unit — this generally means defining it in a "source" file, not a header.


Naive fix

So, in your header:

extern int const ITEMS;  // definition found elsewhere

And then, in one .cpp file:

int const ITEMS = 9;

Real fix

But, oops! You need this constant in your headers, because some array sizes rely on it.

So, instead of making one symbol ITEMS that is shared between all translation units in your program, you will have to have a definition local to each translation unit. To do this, we use the static keyword to make the symbol file-static.

So, in your header:

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

Now, multiple translation units (loosely speaking, this means each .cpp that uses this header) will have their own version of ITEMS, just as before... but this time, because they're marked static, each is local to that translation unit, so they will not conflict at link-time.

Upvotes: 5

Related Questions