Неопределенная ссылка на Class::function()

У меня есть три файла:

  1. main.cpp
  2. RotaryEncoder.h
  3. RotaryEncoder.cpp

Обратите внимание, что класс RotaryEncoder действует как оболочка для библиотеки Encoder. Я получаю следующий отчет о сборке и не могу найти ошибку за последние пару дней:

Построение выходных данных из PlatformIO в VS Code

Processing uno (platform: atmelavr; board: uno; framework: arduino)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelavr/uno.html
PLATFORM: Atmel AVR 1.15.0 > Arduino Uno
HARDWARE: ATMEGA328P 16MHz, 2KB RAM, 31.50KB Flash
PACKAGES: toolchain-atmelavr 1.50400.190710 (5.4.0), framework-arduinoavr 4.1.2
LDF: Library Dependency Finder
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 7 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <Encoder>
Building in release mode
Compiling .pio/build/uno/src/main.cpp.o
Linking .pio/build/uno/firmware.elf
/var/folders/t1/fyh283nd1m7dxbrjlkjtf_kc0000gn/T//ccZN56Tq.ltrans0.ltrans.o: In function `main':
<artificial>:(.text.startup+0x2dc): undefined reference to `RotaryEncoder::getCount()'
collect2: error: ld returned 1 exit status
*** [.pio/build/uno/firmware.elf] Error 1

Явная ошибка

В функции 'main': :(.text.startup+0x2dc): неопределенная ссылка на 'RotaryEncoder::getCount()'.


main.cpp

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

#define cartEncoderPhaseA 3
#define cartEncoderPhaseB 4
#define pendulumEncoderPhaseA 2
#define pendulumEncoderPhaseB 5

// Инициализируем энкодеры
const double ENCODER_PPR = 2400.0;
RotaryEncoder cartEncoder(cartEncoderPhaseA, cartEncoderPhaseB, ENCODER_PPR);
RotaryEncoder pendulumEncoder(pendulumEncoderPhaseA, pendulumEncoderPhaseB, ENCODER_PPR);

void setup()
{
  Serial.begin(9400);
}

void loop()
{
  long cartCount = cartEncoder.getCount();
}

RotaryEncoder.h

#pragma once

#include <Encoder.h>

class RotaryEncoder
{
private:
    Encoder encoder;
    double encoderPPR;
    double angleLowerBound;
    double angleUpperBound;

    double convertEncoderCountToRadians(long encoderCount);
    double normalizeAngle(double angle);

public:
    RotaryEncoder(int phaseA, int phaseB, double encoderPPR);
    long getCount();
    double getRadiansAndOffsetBy(double angleOffset);
    void setAngleLowerAndUpperBounds(double lowerBound, double upperBound);
};

RotaryEncoder.cpp

#include "RotaryEncoder.h"

RotaryEncoder::RotaryEncoder(int phaseA, int phaseB, double encoderPPR) 
: encoder(phaseA, phaseB), encoderPPR(encoderPPR)
{}

inline long RotaryEncoder::getCount()
{
    return encoder.read();
}

inline double RotaryEncoder::getRadiansAndOffsetBy(double angleOffset)
{
    long encoderCount = getCount();
    double angleInRadians = angleOffset + convertEncoderCountToRadians(encoderCount);
    angleInRadians = normalizeAngle(angleInRadians);

    return angleInRadians;
}

inline double RotaryEncoder::convertEncoderCountToRadians(long encoderCount)
{
    return ((double)encoderCount / (encoderPPR)) * (2.0 * PI);
}

inline double RotaryEncoder::normalizeAngle(double angle)
{
    // Ограничение угла между [-pi, pi). Вывод в радианах
    // см.: https://stackoverflow.com/questions/11498169/dealing-with-angle-wrap-in-c-code

    angle = fmod(angle + PI, 2 * PI);

    if (angle < 0)
        angle += 2 * PI;

    return angle - PI;
}

inline void RotaryEncoder::setAngleLowerAndUpperBounds(double lowerBound, double upperBound)
{
    angleLowerBound = lowerBound;
    angleUpperBound = upperBound;
}

, 👍0

Обсуждение

Вы пробовали это без встроенных? Бессмысленно иметь встроенный модификатор в файле cpp, поскольку он скомпилирован в RotaryEncoder.o, а все остальное скомпилировано отдельно и не увидит никаких встроенных..., @KIIV

@KIIV Большое спасибо, это сработало. Я даже не думал, что это проблема. Если вы хотите опубликовать в качестве ответа, я приму это, @Hunter


1 ответ


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

3

Модификатор inline не имеет смысла для определений методов в отдельном файле cpp. И, очевидно, это делает код компилируемым, но методы не распознаются как определения методов, а также не распознаются как ошибки (это довольно странно).

В любом случае, если вам не нужны встроенные методы, делайте это непосредственно внутри определения класса.

,