user4819461
user4819461

Reputation:

Double already defined in main.obj

I'm currently stuck on a problem. It asks to print monthly sales for some kind of store inventory management thingy and then ask the user to enter a number between 1-12 to see the total for a particular month.

I'll have to provide you what I have since I did this in Visual Studio (created a blank/empty project so there was no "stdafx.h" file. Should it be there?):

Sales.h:

#pragma once

#ifndef DEPTS
#define DEPTS 2
#endif

#ifndef STORES
#define STORES 2
#endif

#ifndef MONTHS
#define MONTHS 12
#endif

using namespace std;

double storeMonthlySales[STORES][MONTHS][DEPTS] = {
    {
        {1.1, 1.2}, {1.3, 1.4}, {1.5, 1.6}, {1.7, 1.8}, {1.9, 2.0}, {2.1, 2.2},
        {2.1, 2.2}, {2.3, 2.4}, {2.5, 2.6}, {2.7, 2.8}, {2.9, 3.0}, {3.1, 3.2}
    },
    {
        {3.1, 3.2}, {3.3, 3.4}, {3.5, 3.6}, {3.7, 3.8}, {3.9, 4.0}, {4.1, 4.2},
        {2.1, 2.2}, {2.3, 2.4}, {2.5, 2.6}, {2.7, 2.8}, {2.9, 3.0}, {3.1, 3.2}
    }
};

void printMonthlySales(double ss[DEPTS][MONTHS][STORES], int mon);

Sales.cpp:

#include "Sales.h"
#include <iostream>

using namespace std;

void printMonthlySales(double ss[DEPTS][MONTHS][STORES], int mon)
{
    if ((mon < 1) || (mon > MONTHS))
    {
        cout << "\nMonth must be a number (1 = January, through 12 = December). Try again. \n" << endl;
    }
    else
    {
        double store_total = 0;
        double dept_total = 0;
        double total = 0;

        cout << "\t\t";
        for (int h = 0; h < DEPTS; h++)
        {
            cout << "Department " << h + 1 << "\t\t";
        }
        cout << "Store Total" << endl;
        for (int i = 0; i < STORES; i++)
        {
            cout << "Store " << i << "\t\t";
            for (int j = 0; j < DEPTS; j++)
            {
                double d = ss[j][mon][i];
                cout << d << "\t\t";
                store_total += d;
                total += d;
            }
            cout << endl;
        }
        cout << "Department Total\t";
        for (int i = 0; i < DEPTS; i++)
        {
            for (int j = 0; j < STORES; j++)
            {
                double d = ss[j][mon][i];
                cout << d << "\t\t";
            }
        }
        cout << total << "\t\t" << endl;
    }
}

And this is what I have so far for main.cpp. It's not complete at the moment but I'm just making sure I'm on the right track:

main.cpp:

#include "Sales.h"
#include <algorithm>
#include <iostream>
#include <sstream>

using namespace std;

int main(void)
{
    printMonthlySales(storeMonthlySales, 1);
    string a;
    cin >> a;
    return 0;
}

So what I have so far should printMonthlySales for storeMonhtlySales for month 1 (January). The "string a" and "cin >> a" were just there to prevent the terminal window from closing automatically (again, I'm doing this in Visual Studio).

However, I'm compiling these and I get two errors:

LNK2005 "double (* storeMonthlySales)[12][2]" (?storeMonthlySales@@3PAY1M@1NA) already defined in main.obj
LNK1169 one or more multiply defined symbols found

I'm baffled as to why they say the printMonthlySales is "already defined" since I see nothing wrong here. Looking through the Sales.obj and main.obj files did nothing.

Upvotes: 0

Views: 252

Answers (2)

user4581301
user4581301

Reputation: 33952

When you include a file, it is effectively copied and pasted into the including file. Everything in the header is now part of the the file being compiled.#pragma once, and other forms of include guards prevent a file from being included more than once in a translation unit.

But...

Translation units are compiled separately, so there is no continuity between them. There is no way for B.cpp to know that A.cpp has already included a given header. In fact, think of how bad things would be if only one file in a large project could #include <string>. C++ would have been discarded as a waste of time before it even got out of the office and into the hallway at Bell Labs.

So... A.cpp and B.cpp both include header.h. They both have their own copy of everything in header.h. Both compiled just fine, but the linker has no idea what to do with the competing definitions.

The Solution:

In sales.h:

extern double storeMonthlySales[STORES][MONTHS][DEPTS];

extern is a promise that somewhere storeMonthlySales will be defined so that the compiler can carry on doing it's work. If it isn't defined, the linker will complain.

In Sales.cpp:

double storeMonthlySales[STORES][MONTHS][DEPTS] = {
    {
        {1.1, 1.2}, {1.3, 1.4}, {1.5, 1.6}, {1.7, 1.8}, {1.9, 2.0}, {2.1, 2.2},
        {2.1, 2.2}, {2.3, 2.4}, {2.5, 2.6}, {2.7, 2.8}, {2.9, 3.0}, {3.1, 3.2}
    },
    {
        {3.1, 3.2}, {3.3, 3.4}, {3.5, 3.6}, {3.7, 3.8}, {3.9, 4.0}, {4.1, 4.2},
        {2.1, 2.2}, {2.3, 2.4}, {2.5, 2.6}, {2.7, 2.8}, {2.9, 3.0}, {3.1, 3.2}
    }
};

this is the definition. It only exists in Sales.cpp. It is usable by any file that includes Sales.h

By the way, watch out for using namespace std;. It will cause you problems.

Upvotes: 1

Brandon Lyons
Brandon Lyons

Reputation: 463

Because you put the definition for storeMonthlySales in Sales.h, it gets redefined every time something includes Sales.h. In your case, that's happening twice - once in Sales.cpp and again in main.cpp. A common misconception is that #pragma once (and header guards) will prevent this - they don't. They protect from including the associated .cpp file multiple times, but not the .h itself. So the solution is to move your storeMonthlySales definition to Sales.cpp.

Upvotes: 0

Related Questions