ошибка компиляции atmel studio ifndef

Привет имый проект распознает двойные определения переменных, которые не существуют 2 раза. Я полагаю, что каким-то образом, изменив мой код и перекомпилировав его, он застрял.

LedMatrix7219.cpp.o:(.data.Alphaletter+0x0): множественное определение `Alphaletter' LedController.cpp.o:(.data.Alphaletter+0x0): впервые определено здесь

LedMatrix7219.cpp.o:В функции `loop' LedController.cpp.o:(.bss.arr+0x0): впервые определено здесь

LedMatrix7219.cpp.o:В функции `loop' LedController.cpp.o:(.data.Alphaletter2+0x0): впервые определено здесь

collect2.exe *: ошибка: ld вернул 1 статус выхода

У меня есть класс LedController и заголовок LettersDefinition.h

Все заголовки начинаются так:

Я включаю структуру и перечисление из LetterDefinition.h в LedController, поэтому в заголовке мне нужно включить LetterDefinition.h, чтобы сделать определенный удар.

#ifndef __LEDCONTROLLER_H__
#define __LEDCONTROLLER_H__

#include <Arduino.h>
#include "LettersDefinition.h"

LetterStruct finalText;
String theText="Test";

void test();
//it does some extra staff
#endif //__LEDCONTROLLER_H__

И заголовок письма определение.

#ifndef LETTERSDEFINITION_H_
#define LETTERSDEFINITION_H_

#include "arduino.h"
#include <avr/pgmspace.h>

struct LetterStruct{

    lettersEnum name;
    uint8_t size;
    uint8_t columnSize[5];
    uint8_t data[18];
}Alphaletter;
#endif /* LETTERSDEFINITION_H_ */

И из моего основного файла .ide я вызываю тестовую функцию Ledcontroller и получаю ошибку, которую вы видите выше. Тестовая функция просто проверяет переменную LetterStruct.name и ничего больше.

Мой .ide выглядит примерно так:

#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
#include "LedController.h"   

LedController controller;

void setup()
{
    //irrelevant inits
}

void loop()
{
    controller.test();
    delay(2000);
}

Если я удаляю #include "LettersDefinition.h" из LedController.h, эта ошибка уступает место ошибке, заключающейся в том, что LetterStruct не определен в LedController.h, что нормально, поскольку мне нужно добавить LettersDefinition.h, чтобы быть определен.


person kyrpav    schedule 18.04.2015    source источник
comment
Вы уверены, что не хотели определить это как тип?   -  person Ignacio Vazquez-Abrams    schedule 18.04.2015
comment
как вы видите, я просто объявляю определенный удар типа letterstruct, это все, что я делаю. Удар определяется в letterDefinition.h   -  person kyrpav    schedule 18.04.2015
comment
Затем вы объявляете переменную этого типа с именем Alphaletter.   -  person Ignacio Vazquez-Abrams    schedule 18.04.2015
comment
я объявляю, а затем инициирую алфавит и в тестовой функции я пытаюсь проверить переменную alphaletter.name   -  person kyrpav    schedule 19.04.2015
comment
Да, и вы объявляете его в двух разных единицах компиляции.   -  person Ignacio Vazquez-Abrams    schedule 19.04.2015
comment
почему вы так говорите. если я набираю int favNumber=5 в одном заголовке, а затем перехожу к другому заголовку, включаю первый и che if(favNumber==10){//и делаю что-то} почему я объявляю это дважды   -  person kyrpav    schedule 19.04.2015
comment
Заголовки не являются единицами компиляции.   -  person Ignacio Vazquez-Abrams    schedule 19.04.2015
comment
Давайте продолжим обсуждение в чате.   -  person kyrpav    schedule 19.04.2015
comment
возможный дубликат несколько определений - фиктивная ошибка GCC   -  person Ignacio Vazquez-Abrams    schedule 19.04.2015


Ответы (1)


Ваша проблема возникает из-за того, что вы «определяете» переменные в файлах заголовков. Обычно это приводит к проблеме множественного определения и не является стандартным дизайном.

Модель, которой вам нужно следовать, - это определить один раз в исходном файле:

//some.cpp
// this is define
int variableX = 5;

И объявить в заголовочном файле:

//some.h
// this is declare
extern int variableX;

Каждый другой исходный файл, который включает в себя заголовок, просто обрабатывает строку «extern», которая примерно говорит: «в окончательной программе будет существовать переменная intX». Компилятор просматривает каждый файл .cpp .c и создает модуль. Для файла some.cpp, определяющего переменную, будет создана переменнаяX. Все остальные файлы .cpp будут иметь только внешнюю ссылку, которая является заполнителем. Компоновщик разрешит эти заполнители, когда объединит все модули вместе.

В вашем конкретном случае это означает изменение:

// .h file should only be externs:
extern LetterStruct finalText;
extern String theText;

// .cpp file contains definitions
LetterStruct finalText;
String theText="Test";
person jdr5ca    schedule 18.04.2015
comment
поскольку я хочу использовать finalText внутри класса и переменную thetext, я также полагаю, что с ними нет проблем. потому что таким образом каждая переменная каждого класса должна была быть внешней, чтобы определиться в cpp и не иметь проблем - person kyrpav; 19.04.2015
comment
Переменные-члены класса не используют extern. - person jdr5ca; 19.04.2015