Ошибка: function was not declared in this scope when using a library without classes

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

#include "Lib.h"

// Определение foo1
static void foo1(){
    foo2();
}

// Определение foo2
static void foo2() {}

При включении библиотеки в пустой скетч и его компиляции я получаю следующее сообщение об ошибке:

ошибка: 'foo2' не был объявлен в этой области

В чем здесь проблема?

, 👍0

Обсуждение

Какое это имеет отношение к Ардуино? Я думаю, что это общий вопрос C/C++. Вы написали этот вопрос и ответили на него непосредственно для документирования этого?, @chrisl

Вероятно, этот вопрос применим и в более широком смысле, как и многие другие вопросы на этом сайте. Да, я написал и ответил на этот вопрос для документации., @LukasFun

ваша Lib.h неверна. это сломало автоматическую генерацию форвардных объявлений, @Juraj

он компилируется в Arduino IDE 1.8.10 с пустым Lib.h, @Juraj

теперь я вижу свою ошибку. Я думал у тебя функции в .ino, а ты пишешь, что это .cpp. поэтому в c/c++ вы не можете использовать функции, определенные позже в коде, поэтому вы должны использовать предварительные объявления/прототипы функций, но так было 50 лет назад, так что на самом деле это не проблема Arduino., @Juraj


1 ответ


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

1

При создании библиотеки с функциями, не упомянутыми в заголовочном файле, внезапно становится актуальным порядок появления в файле .cpp. Чтобы функция могла использоваться другой функцией, ее необходимо сначала объявить.

Первой возможностью в этом примере было бы определение foo2 перед определением foo1 следующим образом:

#include "Lib.h"

// Определение foo2
static void foo2() {}

// Определение foo1
static void foo1(){
    foo2();
}

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

Более элегантный и надежный способ сделать это — сначала объявить каждую функцию, как обычно, в заголовочном файле, а затем определить, что они на самом деле делают. Тогда файл .cpp этой библиотеки будет выглядеть следующим образом:

#include "Lib.h"

static void foo1(); // Объявление foo1
static void foo2(); // Объявление foo2

// Определение foo1
void foo1(){
    foo2();
}

// Определение foo2
void foo2() {}
,

Примечание: Эти объявления (static void foo1() и static void foot2() называются предварительными объявлениями., @Michel Keijzers