C ++ - организация служебного кода, избегая «множественного определения ..»

0

Я хочу иметь некоторую глобальную карту, которую следует использовать во многих местах, и несколько обычно используемых небольших функций. Вот как я пытаюсь его организовать.

util.h:

#ifndef UTIL_H
#define UTIL_H

#include <unordered_map>

namespace util {

extern std::unordered_map<std::string, short> rgb2short {
    { "000000", 0 },
    { "800000", 1 },
    { "008000", 2 },
    { "808000", 3 },
    { "000080", 4 },
    /* ... and so on */
};

short some_util_func() {
   /* some util code here */
}

}
#endif

somefile.cpp:

#include "util.h"

/* usage of util::rgb2short and util::some_util_func() */

someotherfile.cpp:

#include "util.h"

/* usage of util::rgb2short and util::some_util_func() */

Компилятор не принимал и не ответил многочисленными multiple definition of 'util::rgb2short' и т.д.

Итак, вопрос в том, как лучше использовать эту вещь.

  • 1
    удалите ключевое слово extern - вы предоставляете определение в util.h, а не извне
  • 0
    Почему вы пытаетесь инициализировать вашу карту в заголовочном файле. И почему ваша реализация функции в вашем заголовке без вложений? (что все еще не является правильным решением для того, что вы пытаетесь сделать).
Теги:
g++

2 ответа

3
Лучший ответ

По крайней мере, когда дело доходит до данных, заголовок должен включать только объявление. Это объявление должно содержать ключевое слово extern и (часть, которую вы сделали неправильно) не должна содержать инициализатор.

Единственное исключение из этого (и это не общий вообще) - это если вы хотите получить отдельную копию данных для каждой единицы перевода, в которую включен заголовок. В этом конкретном случае вам нужно указать, что данные являются static а не extern.

В вашем случае util.h должен содержать только rgb2short декларацию rgb2short. Определение (включая инициализатор) должно быть в каком-то файле .cpp (например, util.cpp). Аналогично, util.h не должен включать определение some_util_func(). Он должен включать только объявление и (опять же) определение, помещенное в исходный файл, такой как util.cpp.

Итак, util.h будет выглядеть следующим образом:

#ifndef UTIL_H
#define UTIL_H

#include <unordered_map>

namespace util {

extern std::unordered_map<std::string, short> rgb2short;

short some_util_func();

}
#endif

Util.cpp будет выглядеть так:

#include "util.h"

namespace util {

std::unordered_map<std::string, short> rgb2short {
    { "000000", 0 },
    { "800000", 1 },
    { "008000", 2 },
    { "808000", 3 },
    { "000080", 4 },
    /* ... and so on */
};

short some_util_func() {
   /* some util code here */
}

}

Тогда вы бы #include "util.h" же, как и вы, но также и ссылку util.obj (или util.o или что-то вроде объектного файла) с другими объектными файлами.

1

Вы должны поместить объявление в заголовок и определение в исходный файл, например:

util.h

#ifndef UTIL_H
#define UTIL_H

#include <unordered_map>

namespace util {
    extern std::unordered_map<std::string, short> rgb2short;
}

#endif

и в util.cpp:

#include "util.h"

namespace util {

    std::unordered_map<std::string, short> rgb2short {
        { "000000", 0 },
        { "800000", 1 },
        { "008000", 2 },
        { "808000", 3 },
        { "000080", 4 },
        /* ... and so on */
    };

}

Это позволит избежать этих ошибок. Для функции отметьте ее как inline и поместите код в заголовок или просто поместите подпись в заголовок (нет необходимости в extern) и поместите тело в файл CPP.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню