Reputation: 25
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
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
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
Reputation: 385365
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.
So, in your header:
extern int const ITEMS; // definition found elsewhere
And then, in one .cpp file:
int const ITEMS = 9;
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