Поиск ответов на этот вопрос дал несколько ответов, которые не имели большого смысла для меня как начинающего программиста на C.
Я программирую Arduinos, большинство из которых подключено к сети, и большинство из них включает датчик температуры для получения MAC-адреса. Все они публикуют сообщения через MQTT.
Мой файл .cpp выглядит так:
/*
Some description
*/
/* --------------- Configuration file --------------------------------------- */
#ifndef CONFIG_H
# include "config.h"
#endif
/* --------------- Libraries ------------------------------------------------ */
#include <Arduino.h> // basic Arduino definitions
#include <avr/wdt.h> // watch dog
#include <stdbool.h> // boolean definition
#include <SPI.h> // Serial Peripheral Interface Bus
#include <Ethernet.h> // Ethernet library for EtherShield
#include <PubSubClient.h> // MQTT client library
#include <OneWire.h> // OneWire library for Dallas DSB etc.
// ----- global variables
...
/* --------------- Instantiate global objects ------------------------------- */
EthernetClient ethernet_client; // Ethernet
PubSubClient mqtt_client (ethernet_client); // instantiate MQTT with ethernet_client
/* --------------- Prototypes ----------------------------------------------- */
// common static code modules
void mac_address_build (uint8_t pin);
void ethernet_connection_maintain ();
void bicolour_led_set (uint8_t ledState);
char *deblank (char *str);
void mac_address_publish ();
void message_publish (const char *topic, const char *msg);
void error_publish (uint8_t error_type, char *error_msg);
void temperature_collect ();
float temperature_get (uint8_t pin);
float temperature_validate (uint8_t pin, float temp_sensed);
void temperature_publish (float temp);
// common code but modify as required
bool b_connected_to_broker ();
void mqtt_call_back (char *topic, byte *payload, uint16_t length);
// controller specific functions
void meter_pulse_counter_isr();
void meter_values_calculate();
void meter_values_publish (float litres_total);
void soil_permittivity_measure();
/* --------------- Function declarations ------------------------------------ */
// as prototype above
void setup ()
{
}
void loop ()
{
}
Я подумал, что просто поместите стандартные модули статического кода и поместите их в standard_functions.cpp и включите его после config.h, например:
/* --------------- Standard functions --------------------------------------- */
#ifndef STD_FUNCTIONS
#define STD_FUNCTIONS
# include "standard_functions.cpp"
#endif
Однако затем я получаю сообщения об ошибках, что идентификаторы не объявлены.
Я хотел бы иметь эти общие модули в отдельном файле, который я включаю в main.cpp, чтобы я мог поддерживать один включаемый файл для всех других программ, которые я мог бы написать.
Я прочитал: Следует ли мне использовать #include в заголовках? Как разделить это на заголовочный и исходный файлы? Как разделить код на несколько файлов
... что я не мог применить к моей «проблеме». Один даже предлагает мне создать еще один файл .h (в дополнение к .cpp).
Что касается терминологии, я предполагаю, что .h означает файл заголовка, но у которого может быть любое другое имя, если оно заканчивается на .h ?!
Возможно ли, что это обычная практика, чтобы мои «стандартные_функции» содержались в одном файле (.cpp или .h), или мне нужны стандартные_functions.h и .cpp? Что есть в каждом? Когда я создаю standard_function.cpp и помещаю в него функции, я получаю около 70 сообщений с неопределенным идентификатором. Однако, когда я переименовываю standard_functions.cpp в .h, я получаю только одно сообщение об ошибке, которое, кажется, указывает на то, что это лучшее имя. Ошибка - переменная или поле mac_address_build объявлено недействительным; хотя код компилируется без ошибок, если все находится в одном файле. Однако при перемещении этой функции на второе место появляется больше ошибок о неопознанных идентификаторах.
Я разбивал файлы разными способами, и сообщения об ошибках продолжали накапливаться. Так что да, я не «понял».
.cpp
файлы. Предполагается, что источник CPP будет скомпилирован в объектный файл, а заголовки должны предоставить типы и интерфейсы, необходимые для ссылки на материал в этом объектном файле. Позже компоновщик объединяет все ваши объектные файлы вместе. Короче говоря, заголовок должен предоставлять объявления функций и типов, а исходный файл должен предоставлять фактическую реализацию. - person paddy   schedule 25.09.2020#include
. Также рассмотрите#pragma once
как альтернативу. - person bitmask   schedule 25.09.2020