c++ - Arduino IDE中自定义库类的.h文件编译错误的原因是什么

标签 c++ c++11 arduino arduino-uno arduino-ide

我正在使用 Energia(Arduino 的一个分支)为机器人开发程序。我决定创建一个由单个类组成的库来处理位置和距离计算。

当我尝试使用该类时,我看到了我不理解的编译器错误。

这是我的 .h 文件:

#ifndef Position
#define Position
#include "Energia.h"
class Position
{
    public:
        Position(int PinEcho, int PinTrig);
        float getDistance(char* Distance);
        float getDistanceMoy(int Nombre,char* unite);
    private:
        int _pinEcho;
        int _pinTrig;

};
#endif

.cpp 文件包含:

#include "Energia.h" //Arduino.h if we are using Arduino
#include "Position.h"

Position::Position(int pinEcho,int pinTrig)
{
    pinMode(pinEcho, OUTPUT);
    pinMode(pinTrig, INPUT);
    digitalWrite(pinTrigger, LOW);
    int _pinEcho = pinEcho;
    int _pinTrig = pinTrig;
    const unsigned long MEASURE_TIMEOUT = 25000UL;
    const float SOUND_SPEED = 340 / 1000;
}

float Position::getDistance(char* mode){
    digitalWrite(pinTrigger, LOW);
    digitalWrite(pinTrigger, HIGH);
    delayMicroseconds(10);
    digitalWrite(pinTrigger, LOW);
    long mesure = pulseIn(pinEcho,HIGH,MEASURE_TIMEOUT);
    float distance = mesure / 2 * SOUND_SPEED;
    if(mode =="cm") distance = distance / 10;
    if(mode =="dm") distance = distance / 100;
    if(mode == "m") distance = distance / 1000;
    return distance;
}

float Position::getDistanceMoy(int maxi,char* mode){
    int i=0, j=0;
    int distMoy = 0;
    while(i != maxi ){
        digitalWrite(pinTrigger, LOW);
        digitalWrite(pinTrigger, HIGH);
        delayMicroseconds(10);
        digitalWrite(pinTrigger, LOW);
        long mesure = pulseIn(pinEcho,HIGH,MEASURE_TIMEOUT);
        float distance = mesure / 2 * SOUND_SPEED;
        if(distance != 0){
            distMoy += distance;
            j++;
        }
        i++;
    }
    distMoy = distMoy/j;
    if(mode =="cm") distMoy = distMoy / 10;
    if(mode =="dm") distMoy = distMoy / 100;
    if(mode == "m") distMoy = distMoy / 1000;
    return distMoy;
}

然后我使用 #include <Position.h> 在 Arduino 上导入库然后初始化它:

Position position(Variable1,Variable2);

但是当我想使用它和 Energia(或 Arduino)时,我得到了这些错误:

In file included from C:\Users\alex9\Documents\Energia\sketch_may10a\sketch_may10a.ino:1:0:
C:\Users\alex9\Documents\Energia\libraries\Position/Position.h:15:18: error: expected unqualified-id before 'int'
         Position(int PinEcho, int PinTrig);
                  ^
C:\Users\alex9\Documents\Energia\libraries\Position/Position.h:15:18: error: expected ')' before 'int'
C:\Users\alex9\Documents\Energia\libraries\Position/Position.h:13:1: error: an anonymous struct cannot have function members
 {
 ^
C:\Users\alex9\Documents\Energia\libraries\Position/Position.h:22:1: error: abstract declarator '<anonymous class>' used as declaration
 };
 ^
sketch_may10a:8: error: expected constructor, destructor, or type conversion before '(' token
 Position position(PinEcho,PinTrig);
                  ^
exit status 1 expected constructor, destructor, or type conversion before '(' token

我不理解这些错误消息,也不知道我需要修复什么。有人可以帮助我吗?

最佳答案

在您的 .h 文件中,您有以下文本行是预处理器命令:

  • 检查是否定义了预处理器宏“Position”
  • 如果未定义则将其定义为空或无文本

一旦预处理器为宏“Position”做了这个宏定义,那么当预处理器继续进行它的源文本处理时,它所做的其中一件事就是每次它找到标记“Position”时它都会用它的标记替换那个标记定义值,在本例中为空字符串。

#ifndef Position
#define Position

使用Preprocessor时一定要记住,它是一个额外的处理步骤,与编译无关。这是一个纯文本处理步骤,用于在将源文本输入编译器之前修改源文本,这是一个完全独立的步骤。

您可以通过单独运行预处理器并查看生成的输出文件来检查发生了什么。虽然通常是编译器开关,但编译器之间的完成方式会有所不同。

将预处理器守卫放入 .h 文件的典型方法是执行类似此示例的操作。这个用于包含文件保护的预处理器宏由包含文件的名称后跟字母“H”和单词“included”组成,各个部分用下划线连接:

#ifndef POSITION_H_INCLUDED
#define POSITION_H_INCLUDED

通过使用此宏名称,宏名称与源文件中的某些变量或类或结构名称/标签或其他文本标记之间发生冲突的可能性会大大降低。

此命名约定为您做了几件事。

首先,它全部使用大写,这是预处理器宏名称的事实标准。

其次,它很好地描述了这个宏名称的意图。

第三,其他一些文本标记相同的可能性相当小,因此出现您遇到的错误的可能性很小。

大型源代码的命名方法

但是对于一个大型项目,如数十万行代码和数千个文件,不同库中的不同包含文件可能使用相同的名称。同样的问题是为什么 namespace 概念是用 C++ 发明的。

因此,使用添加到宏名称的一些额外文本的更复杂的名称会增加宏名称唯一的可能性。一种方法是将库名称或制造商名称添加到宏名称中。

#ifndef POSITION_H_INCLUDED_POSITION_LIB_MICHAUD
#define POSITION_H_INCLUDED_POSITION_LIB_MICHAUD

一个简单的方法是将日期和时间添加到宏名称中,如下所示:

#ifndef POSITION_H_INCLUDED_20180517_1021_00
#define POSITION_H_INCLUDED_20180517_1021_00

一些 IDE 会为您做一些类似的事情,作为为类生成源代码之类的事情的一部分。下面是一个来自旧版 Visual Studio C++ IDE 的示例,它生成了一个 MFC 类包含文件。这有点矫枉过正,因为 IDE 似乎生成了一个非常独特的 GUID,并使用它来创建 99.999999999% 可能是唯一的预处理器宏名称或标识符的内容。请注意,作为生成此宏名称的一部分,IDE 使用了包含文件的名称、字母“H”和单词“included”以及 GUID。

#if !defined(AFX_OPOSCASHDRAWER_H__86921069_045D_4880_A41A_5A18F0E5FABD__INCLUDED_)
#define AFX_OPOSCASHDRAWER_H__86921069_045D_4880_A41A_5A18F0E5FABD__INCLUDED_

另请注意,IDE 生成的预处理器指令正在使用 defined() 运算符。这允许您通过预处理器的 #if 指令使用更复杂的逻辑操作。

查看此 Wikipedia article, C Preprocessor有关预处理器的更多详细信息。此 Material 也适用于预处理器的大多数 C++ 版本。

关于c++ - Arduino IDE中自定义库类的.h文件编译错误的原因是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50379725/

相关文章:

c++ - 如何将 write() 系统调用设置为 "flush"?

c++ - auto&& 是做什么的?

c++ - 一旦对 std::weak_ptr 的锁定返回了 nullptr,它还能再次为非空吗?

对象中的 C++ 对象

安卓和蓝牙挂起(startActivityForResult)

c++ - 重载 Iostream C++

c++ - 使用 lower_bound 的结果作为 upper_bound 的参数(反之亦然)

c++ - const_cast 未定义行为的重要示例

c++ - 我怎么知道 C++ 编译器是否在编译时计算表达式?

c++ - 编译Arduino代码(NodeMCU)时出错