Double уже определен в main.obj - PullRequest
0 голосов
/ 08 февраля 2019

Я в настоящее время застрял в проблеме. Он запрашивает распечатку ежемесячных продаж для какой-то вещи, связанной с управлением запасами в магазине, и затем просит пользователя ввести число от 1 до 12, чтобы увидеть общее количество дляконкретный месяц.

Я должен предоставить вам то, что у меня есть, так как я сделал это в Visual Studio (создал пустой / пустой проект, чтобы не было файла "stdafx.h". Должен ли он быть там?):

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;
    }
}

И это то, что я до сих пордля main.cpp.Это не завершено в настоящее время, но я просто проверяю, что я на правильном пути:

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;
}

Так что у меня естьдо сих пор следует печатать MonthlySales для storeMonhtlySales за месяц 1 (январь).«Строка a» и «cin >> a» были как раз там, чтобы предотвратить автоматическое закрытие окна терминала (опять же, я делаю это в Visual Studio).

Однако я компилирую их и получаю две ошибки:

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

Я сбит с толку относительно того, почему они говорят, что printMonthlySales "уже определен", поскольку я не вижу в этом ничего плохого,Просмотр файлов Sales.obj и main.obj ничего не сделал.

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

Когда вы включаете файл, он эффективно копируется и вставляется во включающий файл.Все в заголовке теперь является частью файла, который компилируется. #pragma once, а другие формы встроенных средств защиты предотвращают включение файла более одного раза в единицу перевода .

Но ...

Единицы перевода составляются отдельно, поэтому между ними нет преемственности.B.cpp не может знать, что A.cpp уже включил данный заголовок.На самом деле, подумайте о том, насколько плохи были бы дела, если бы только один файл в большом проекте мог #include <string>.C ++ был бы отброшен как пустая трата времени, прежде чем он даже вышел из офиса в коридор в Bell Labs.

Итак ... A.cpp и B.cpp оба включают header.h.У них обоих есть своя копия всего в header.h.Оба компилируются просто отлично, но компоновщик понятия не имеет, что делать с конкурирующими определениями.

Решение:

В sales.h:

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

extern - это обещание, что где-то будет определено storeMonthlySales, чтобы компилятор мог продолжать выполнять свою работу.Если он не определен, компоновщик будет жаловаться.

В 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}
    }
};

это определение.Он существует только в Sales.cpp.Он может использоваться любым файлом, который включает Sales.h

. Кстати, следите за using namespace std;.Это вызовет у вас проблемы.

0 голосов
/ 08 февраля 2019

Поскольку вы помещаете определение для storeMonthlySales в Sales.h, оно переопределяется каждый раз, когда что-то включает Sales.h.В вашем случае это происходит дважды - один раз в Sales.cpp и снова в main.cpp.Распространенным заблуждением является то, что #pragma once (и охранники заголовков) предотвратят это - они этого не делают.Они защищают от включения связанного файла .cpp несколько раз, но не самого .h.Поэтому решение состоит в том, чтобы переместить ваше определение storeMonthlySales в Sales.cpp.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...