【问题标题】:Error: redefinition of class, despite using include guards错误:重新定义类,尽管使用了包含守卫
【发布时间】:2020-11-29 04:26:44
【问题描述】:

我是 javascript/typescript 开发人员,但对 Arduino/c++ 很陌生

我有一个类(见下面的 h 和 cpp)并且有这个编译器错误:

DotMatrix.cpp:13:1: error: redefinition of 'DotMatrix::DotMatrix(uint8_t, MD_MAX72XX::moduleType_t, uint8_t, uint8_t, uint8_t)'
 DotMatrix::DotMatrix(uint8_t maxDevices, MD_MAX72XX::moduleType_t hardwareType, uint8_t clkPin, uint8_t dataPin, uint8_t csPin) 
 ^
In file included from sketch/DotMatrix.cpp:5:0:
DotMatix.h:10:3: error: 'DotMatrix::DotMatrix(uint8_t, MD_MAX72XX::moduleType_t, uint8_t, uint8_t, uint8_t)' previously defined here
   DotMatrix(uint8_t maxDevices, MD_MAX72XX::moduleType_t hardwareType, uint8_t clkPin, uint8_t dataPin, uint8_t csPin) 
   ^
exit status 1

我不明白为什么......

这里是文件:

DotMatix.h:

#ifndef DotMatrix_h
#define DotMatrix_h

#include <MD_MAX72xx.h> 
#include <MD_Parola.h> 

class DotMatrix
{
  public:
    DotMatrix(uint8_t maxDevices, MD_MAX72XX::moduleType_t hardwareType, uint8_t clkPin, uint8_t dataPin, uint8_t csPin) 
    : _parola(hardwareType, csPin, maxDevices)
    {};

    void setup();
  
  private:
    MD_Parola _parola;
};

#endif

DotMatix.cpp:

#ifndef DotMatrix_cpp
#define DotMatrix_cpp

//#include <stdint.h>
#include "DotMatix.h"
#include "Arduino.h"

#include <MD_Parola.h>  // Parola library to scroll and display text on the display (needs MD_MAX72xx library)  https://github.com/MajicDesigns/MD_Parola
#include <MD_MAX72xx.h> // Library to control the Maxim MAX7219 chip on the dot matrix module   https://github.com/MajicDesigns/MD_MAX72XX

const int FRAME_DELAY = 25;

DotMatrix::DotMatrix(uint8_t maxDevices, MD_MAX72XX::moduleType_t hardwareType, uint8_t clkPin, uint8_t dataPin, uint8_t csPin) 
: _parola(hardwareType, csPin, maxDevices)
{
  //MD_Parola(MD_MAX72XX::moduleType_t mod, uint8_t csPin, uint8_t numDevices = (uint8_t)'\001')
  _parola = MD_Parola(hardwareType, csPin, maxDevices);  
}

void DotMatrix::setup()
{
  this->_parola.begin();
  _parola.displayClear();
  _parola.displaySuspend(false);
  byte i = 3;                                            //EEPROM.read(0);
  _parola.setIntensity(i);                               // Values from 0 to 15
  _parola.setTextEffect(PA_SCROLL_LEFT, PA_SCROLL_LEFT); //in and out effect
  _parola.displayScroll("Hallokes ...", PA_LEFT, PA_SCROLL_LEFT, FRAME_DELAY);
}

#endif

作为参考,这是调用该类的 ino 文件(的一个 sn-p):

#include "DotMatix.h"

// Define the number of 8x8 dot matrix devices and the hardware SPI interface
#define MAX_DEVICES 4
#define HARDWARE_TYPE MD_MAX72XX::DR1CR0RR0_HW

#define CLK_PIN   14 //D5
#define DATA_PIN  13 //D7
#define CS_PIN    2  //D4


DotMatrix dotMatrix(MAX_DEVICES, HARDWARE_TYPE, CLK_PIN, DATA_PIN, CS_PIN);

void setup() {
  dotMatrix.setup();
}

void loop() {
}

我正在使用带有 Arduino 扩展的 VS Code IDE。

【问题讨论】:

  • #ifndef DotMatrix_cpp #define DotMatrix_cpp 不,源文件没有包含保护。您已经定义了两个DotMatrix::DotMatrix 函数。错误甚至告诉你在哪里。

标签: c++ class constructor arduino function-definition


【解决方案1】:
void func(); // function declaration
void func() { blablabla; } // function definition.

您可能会看到定义和声明之间的简单区别。一个有{,另一个没有。一个(全局)函数在代码库中只能定义一次,而不是两次。否则你的编译器将不知道选择哪个函数——第一个?第二个?

你做到了:

// in DotMatix.h:
DotMatrix(blablaa)
{}; // yes this is definition

也做了:

// in DotMatrix.cpp
DotMatrix::DotMatrix(ublabla, who cares)
{ // also definition

编译器看到同一个函数的两个定义并退出并报错。

包含保护通常用于防止两次包含同一个文件。您的多个定义在多个文件中。也不需要在源文件中包含保护 - 源文件不应该被包含,因此它们总是会被处理一次。

【讨论】:

    【解决方案2】:

    您定义了两次构造函数。 DotMatrix 的第一个定义在标题 DotMatix.h 中的类定义本身内:

    class DotMatrix
    {
      public:
        DotMatrix(uint8_t maxDevices, MD_MAX72XX::moduleType_t hardwareType, uint8_t clkPin, uint8_t dataPin, uint8_t csPin) 
        : _parola(hardwareType, csPin, maxDevices)
        {};
        //...
    

    注意构造函数定义后的空语句;是多余的。

    这个定义定义了一个内联函数。

    注意构造函数有未使用的参数。

    构造函数DotMatrix的第二个定义在模块DotMatix.cpp内:

    DotMatrix::DotMatrix(uint8_t maxDevices, MD_MAX72XX::moduleType_t hardwareType, uint8_t clkPin, uint8_t dataPin, uint8_t csPin) 
    : _parola(hardwareType, csPin, maxDevices)
    {
      //MD_Parola(MD_MAX72XX::moduleType_t mod, uint8_t csPin, uint8_t numDevices = (uint8_t)'\001')
      _parola = MD_Parola(hardwareType, csPin, maxDevices);  
    }
    

    此外,此定义包含数据成员 _parola 在构造函数主体内的冗余分配。

    完全删除模块DotMatix.cpp中的构造函数定义。

    还有这些守卫指令

    #ifndef DotMatrix_cpp
    #define DotMatrix_cpp
    

    没有多大意义,因为模块并非设计为包含在其他模块中。

    【讨论】:

      【解决方案3】:

      你应该改变 DotMatrix.h 的这一行:

        DotMatrix(uint8_t maxDevices, MD_MAX72XX::moduleType_t hardwareType, uint8_t clkPin, uint8_t dataPin, uint8_t csPin) 
          : _parola(hardwareType, csPin, maxDevices)
          {};
      

      应该是:

         DotMatrix(uint8_t maxDevices, MD_MAX72XX::moduleType_t hardwareType, uint8_t clkPin, uint8_t dataPin, uint8_t csPin) 
              : _parola(hardwareType, csPin, maxDevices);
      

      如果没有,您将直接在头文件中实现构造函数(构造函数什么都不做)。实现是“{}”(无事可做) 然后当编译器在 .cpp 文件中看到另一个实现(正确的)时,它说它已经被定义了。

      【讨论】:

        【解决方案4】:

        感谢所有输入! 我已经删除了 cpp 文件中的构造函数,现在一切正常。 此外,cpp 文件中的包含保护确实是一件愚蠢的事情!

        来自 js / typescript,整个头文件和奇怪的 initialiser list 语法仍在我的脑海中创建快捷方式;-)

        关于初始化列表:这是用带参数的构造函数声明类变量的唯一方法吗?这对我来说看起来很奇怪......

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-01-19
          • 1970-01-01
          • 2012-03-15
          • 2015-07-11
          • 2015-11-29
          • 1970-01-01
          相关资源
          最近更新 更多