Множественная ошибка определения при связывании firmware.elf

compile compilation-errors mkr-gsm-1400 makefile

Я просто не могу понять, как правильно работать с несколькими файлами. Мой код стал довольно большим, поэтому я решил разделить все классы на один файл каждый. Итак, у меня осталось 6 файлов:

dataHandler.cpp
fileHandler.cpp
header.cpp
main.cpp
request.cpp
sensorData.cpp

header.cpp включает все файлы заголовков, а main.cpp — функции setup() иloop().

Visual Studio Code не показывает ошибок при компиляции. Включаемые защиты имеют соглашение об именах: CLASSNAME_INCG

Например, в моем файле main.cpp есть что-то вроде:

#ifndef HEADER_INCG
#include "header.cpp"
#define HEADER_INCG
#endif

#ifndef SENSORDATA_INCG
    #include "SensorData.cpp"
    #define SENSORDATA_INCG
#endif

#ifndef DATAHANDLER_INCG
    #include "DataHandler.cpp"
    #define DATAHANDLER_INCG
#endif

setup()
{
    ...
}

...

При входе в файл класса он определяется следующим образом (fileHandler.cpp):

#ifndef HEADER_INCG
#include "header.cpp"
#define HEADER_INCG
#endif


#ifndef FILEHANDLER_INCG
#define FILEHANDLER_INCG

class FileHandler{
    ...
}

#endif

Итак, вкратце Я включаю заголовочный файл в каждый файл, окружая его защитой. Если бы я не включил его, я бы получил ошибки, из-за которых отсутствуют важные библиотеки, такие как Serial и т. д. Но при включении заголовка в каждый файл компиляция работает нормально, но когда дело доходит до связывания файлов вместе, я получаю ошибку с несколькими определениями.

Так как же я могу определить файл заголовка только один раз для всех файлов, хотя он мне нужен в каждом файле?

, 👍1

Обсуждение

ты неправильно используешь охрану. посмотрите какую-нибудь библиотеку для правильного использования и используйте файлы .h, @Juraj


1 ответ


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

2
  1. Правило №1:
    Расширение заголовочного файла — «.h». Файлы с расширением «.cpp» обычно компилируются как отдельные единицы компиляции в объектный файл. Если у вас есть какое-либо определение функции (= объявление + реализация) или любая глобальная переменная в других объектных файлах, она не сможет связать.

  2. Правило №2:
    Никаких определений в заголовках — переменные и функции вызовут эту ошибку, если вы включите файл .h в другие файлы .cpp. Если вам нужна суперглобальная переменная, вам нужно использовать объявление с модификатором extern и определить ее в одном из файлов .cpp. Но только один! Также в заголовочном файле могут быть только прототипы функций (объявления). Реализация должна быть только один раз в одном из файлов «.cpp».

Обычно это находится в первой главе книг по изучению C/C++.

Очень короткий пример:

// myLib.h
#ifndef _myLib_h_guard_
#define _myLib_h_guard_

void myFunction(); // прототип функции (объявление)

extern int mySuperGlobalVariable;  // переменная объявлена как extern, где-то должно быть ее определение

class MyClass {
public:
  int someMethod(); // объявление метода

  int anotherMethod() { return 1; }  // определение внутри класса работает, но иногда становится менее читабельным
};

#endif
// myLib.cpp
#include "myLib.h"

void myFunction() { // реализация функции (определение)
  // сделай что-нибудь...
}

int mySuperGlobalVariable; // определение

int MyClass::someMethod() { return 2; } // определение метода
// main.cpp
#include <myLib.h>

int main() {

  mySuperGlobalVariable = 10;

  myFunction();

  MyClass instance;
  int first = instance.someMethod();
  int second = instance.anotherMethod();
}
,

Не могли бы вы привести пример, как это правильно сделать? Я уверен, что для вас это звучит тривиально, но я с трудом понимаю, что вы сказали., @Cowboy_Patrick

Большое спасибо :) Я пытался объявить и инициализировать его в myLib.cpp и забыл ключевое слово extern в myLib.h., @Cowboy_Patrick

вы можете использовать #pragma Once вместо старомодного #ifndef _myLib_h_guard_ :p, @Jaromanda X