Понимание ошибки компоновщика C: множественное определение - PullRequest
0 голосов
/ 04 февраля 2019

У меня есть проект с несколькими заголовочными файлами и .cpp файлами.Все заголовочные файлы содержат защитные элементы.

Существует файл с именем Constants.h, в котором я определяю некоторые константы.Некоторые из них с определениями, некоторые как постоянные переменные.

Есть больше пар заголовка- .cpp -файла с кодом в них.Один из них содержит класс, а другие нет.

Когда я включаю свои файлы в свой основной файл (набросок arduino), я получаю много ошибок компоновщика, утверждая, что существует несколько определений некоторыхпеременные.

Я читал, что это в основном происходит, когда вы включаете файлы .c или .cpp, чего я не делаю.Все файлы .cpp содержат только соответствующие им заголовочные файлы.

Мне удалось найти несколько предложений по решению:

1) inline:

С функциями, inline может использоваться, чтобы избавиться от этой проблемы.Однако это невозможно с переменными.

2) анонимный namespace:

Это одно из решений, которое я использовал.Я поместил анонимные пространства имен вокруг всех проблемных определений, которые у меня были.Это сработало, однако я не понимаю, почему это работает.Может ли кто-нибудь помочь мне понять это?

3) перемещение определений в .cpp файлы:

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

Может ли кто-нибудь объяснить мне, где именно проблема и почему эти подходыработа

Ответы [ 3 ]

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

В дополнение к превосходному объяснению Story Teller для определения глобальных переменных используйте следующее:

// module.h
#include "glo.h"

// glo.h
#ifndef EXTERN
# define EXTERN extern
#endif
EXTERN int myvar;

// main.c
#define EXTERN
#include "glo.h"

В main.c будут объявлены все переменные (т. Е. Для них выделено пространство), во всех остальныхc файлами, которые включают glo.h, все переменные будут известны.

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

Вы не должны объявлять какой-либо объект в заголовочных файлах, его следует переместить в файлы c \ c ++.

В заголовке вы можете:

  • объявлять такие типы, как: class es, struct s, typedef s и т. Д.
  • выдвигать объявления функций (не классов)
  • вставлять встроенные (или в классы) функции (+ body)
  • вы можете добавить extern объявление.
  • вы можете поместить свои макросы.

a static объявление может объявлять вещи несколько раз, поэтому это не рекомендуется.

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

Некоторые из них с определением, некоторые как постоянные переменные.

В C const не означает то же самое, что и в C ++.Если у вас есть это:

const int foo = 3;

В заголовке, тогда любой модуль перевода C ++, который включает в себя заголовок, будет иметь статическую переменную с именем foo (const в области пространства именподразумевает внутреннюю связь).Более того, foo может даже рассматриваться как константное выражение во многих конструкциях C ++.

Это не относится к C. В foo есть объект в области видимости файла с внешней связью.Таким образом, у вас будет несколько определений из единиц перевода C.

Быстрое решение состоит в том, чтобы преобразовать определения во что-то вроде этого:

static const int foo = 3;

Это избыточно в C ++, но требуется в C.

...