Я очень смущен тем, что здесь не так. Я получаю ошибку неопределенной ссылки на массив, который я определил так же, как и два других, которые не вызывают ошибок в другом месте кода.
undefined reference to `shift7seg::numbers'
Код shift7seg.cpp, показывающий другую функцию, использующую аналогичные определенные массивы
uint8_t shift7seg::convert_char(const char& OGchar){
uint8_t converted;
switch (OGchar){
case 'A':
converted = capital[0];
break;
case 'h':
converted = lower[3];
break;
//more cases removed for posting
}
return converted;
}
uint8_t shift7seg::convert_num(const uint8_t& OGnum){
uint8_t converted;
if (OGnum<10){
converted = numbers[OGnum];
}
else{
converted = blank;
}
return converted;
}
shift7seg.h, показывающий определения используемых массивов
class shift7seg{
public:
//constructor, choose pins to use as well as display size
shift7seg(const uint8_t _dataPin,
const uint8_t _latchPin,
const uint8_t _clkPin,
const uint8_t _num_digits);
static constexpr uint8_t numbers[10] = // 7 segment values for decimals 0..9
{
//TRUTH TABLE | 0 = segment on
//ABCDEFGH | 1 = segment off
B00000011, //0 | A
B10011111, //1 | -----
B00100101, //2 | F | | B
B00001101, //3 | | G |
B10011001, //4 | -----
B01001001, //5 | E | | C
B01000001, //6 | | |
B00011111, //7 | -----
B00000001, //8 | D
B00011001 //9 |
};
static constexpr uint8_t capital[13] =
{
B00010001, //A or R, 0
B00000001, //B 1
B01100011, //C 2
B00000011, //D or O, 3
B01100001, //E 4
B01110001, //F 5
B01000001, //G 6
B10010001, //H 7
B10000111, //J 8
B11100011, //L 9
B00110001, //P 10
B01001001, //S 11
B10000011 //U or V, 12
};
static constexpr uint8_t lower[9] =
{
B11000001, //b 0
B11100101, //c 1
B10000101, //d 2
B11010001, //h 3
B10011111, //l 4
B11010101, //n 5
B11000101, //o 6
B11110101, //r 7
B11000111 //u or v, 8
};
Диалект C++11. Я не могу в жизни понять, что я сделал не так. Разговор с резиновой уткой пока ничего не дал.
Больше кода ошибки здесь.
more undefined references to `shift7seg::numbers' follow
collect2.exe: error: ld returned 1 exit status
exit status 1
Этот код должен быть совершенно легальным в C++17. Какой у вас диалект С++?
Похоже, этот код компилируется в С++ 11, это единственный компилятор, который я могу использовать в этом случае. как бы это выглядело, определяя статические переменные-члены в другом месте? Будет ли это в моем driver.cpp и присваивать значения как глобальную переменную?
За исключением «constexpr» (C++ 11 или выше), я не вижу никаких причин, по которым это не должно компилироваться и связываться с ЛЮБОЙ версией C++! В: Возможно, тот или иной из ваших объектных файлов, ссылающихся на «shift7seg», не был скомпилирован с помощью C++11?
Я не знаком с этим типом ошибок, но я пытался его скомпилировать. Я получил еще одну ошибку: /usr/bin/ld: /tmp/cckpICDV.o: warning: relocation against '_ZN9shift7seg7numbersE' in read-only section '.text'
. Код становится компилируемым, когда вы меняете OGnum
в доступе к массиву numbers
на некоторую константу, например 2
, однако он также компилируется при переходе на C++17.
@Tanner G - рассмотрите возможность простого удаления «constexpr» и сообщите нам, решит ли это проблему.
@ paulsm4, что вы ожидаете от этого?
Прежде всего, я думаю, что префикс 0B
в этих бинарных литералах, а не B
. Во-вторых, вам нужен С++ 17 для его компиляции из-за статического материала constexpr.
цитировать
Если статический член данных объявлен как constexpr, он неявно встроен и не требует повторного объявления в области пространства имен. Это повторное объявление без инициализатора (ранее требовавшееся, как показано выше) по-прежнему разрешено, но не рекомендуется.
от https://en.cppreference.com/w/cpp/language/static
это весь код для arduino, поэтому правильный тег двоичного литерала - B, я посмотрю, смогу ли я заставить его работать без constexpr
Где-то в вашем коде вы ODR используетеnumbers
, но у вас нет для этого определения.
Вот простая версия вашей проблемы (wandbox):
#include <iostream>
#include <cstdint>
class shift7seg {
public:
static constexpr std::uint8_t numbers[10] = {};
};
int main() {
// taking the address is ODR-use
std::cout << &shift7seg::numbers[0] << '\n';
}
Возможные решения
скомпилировать с помощью -std=c++17
(или более поздней версии), где все статические элементы данных constexpr неявно встроены и не нуждаются во внешних определениях
Добавьте внешнее определение в свой файл реализации (shift7seg.cpp), как это (wandbox):
constexpr std::uint8_t shift7seg::numbers[10];
Похоже, это проблема, добавление определения вне очереди устранило эту ошибку и принесло другие. отладка продолжается, спасибо
Разве вам не нужно определять статические переменные-члены вне самого определения класса?