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

时间:2018-05-16 20:54:10

标签: 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

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

2 个答案:

答案 0 :(得分:4)

在.h文件中,您有以下文本行,这些文本是预处理程序命令:

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

一旦预处理器为宏“位置”执行此宏定义,然后当预处理器继续执行其源文本处理时,它所做的一件事就是每当它找到令牌“位置”时它将用它替换该令牌定义的值,在这种情况下是空字符串。

#ifndef Position
#define Position

使用预处理器时必须记住,这是一个与编译无关的附加处理步骤。它是一个纯文本处理步骤,用于在将源文本送入编译器之前对其进行修改,这是一个完全独立的步骤。

您可以通过单独运行预处理器并查看生成的输出文件来检查发生了什么。如何完成这些工作将在编译器之间有所不同,尽管它通常是编译器开关。

将预处理程序保护放在.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会为您生成类似的东西,作为为类生成源代码的一部分。以下是生成MFC类包含文件的旧Visual Studio C ++ IDE中的示例。这有点过分,因为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生成的Preprocessor指令正在使用defined()运算符。这允许您使用预处理器的#if指令进行更复杂的逻辑运算。

有关预处理器的更多详细信息,请参阅此Wikipedia article, C Preprocessor。此材料也应适用于预处理器的大多数C ++版本。

答案 1 :(得分:0)

您不应该像命名定义一样命名类

define就像一个别名,所以,你的类名被设置为define值,在你的情况下是空字符串。