【问题标题】:No matching function for call in Arduino LibraryArduino库中没有匹配的调用函数
【发布时间】:2016-08-11 20:16:51
【问题描述】:

我正在创建一个用于 Sketch 的 Arduino 库。它使用Encoder Library,但是在编译时我得到一个钝错误:

/var/folders/jy/f8dvlhcd4vdcvtl49bk8ytwc0000gn/T/builda847c0675e0bee2f5f05581e35ae65fe.tmp/sketch/MIDIEncoder.cpp:在构造函数“MIDIEncoder::MIDIEncoder(uint8_t, uint8_t, byte, byte)”中: MIDIEncoder.cpp:8: 错误: 没有匹配函数调用'Encoder::Encoder()' MIDIEncoder::MIDIEncoder(uint8_t pinA, uint8_t pinB, 字节 midiChannel, 字节 midiCCNumber) ^ /var/folders/jy/f8dvlhcd4vdcvtl49bk8ytwc0000gn/T/builda847c0675e0bee2f5f05581e35ae65fe.tmp/sketch/MIDIEncoder.cpp:8:89:注意:候选人是: 在 /var/folders/jy/f8dvlhcd4vdcvtl49bk8ytwc0000gn/T/builda847c0675e0bee2f5f05581e35ae65fe.tmp/sketch/MIDIEncoder.h:17:0 包含的文件中, 来自/var/folders/jy/f8dvlhcd4vdcvtl49bk8ytwc0000gn/T/builda847c0675e0bee2f5f05581e35ae65fe.tmp/sketch/MIDIEncoder.cpp:2: /Applications/Arduino.app/Contents/Java/hardware/teensy/avr/libraries/Encoder/Encoder.h:72:2:注意:Encoder::Encoder(uint8_t, uint8_t) 编码器(uint8_t pin1,uint8_t pin2){ ^ /Applications/Arduino.app/Contents/Java/hardware/teensy/avr/libraries/Encoder/Encoder.h:72:2:注意:候选人需要 2 个参数,提供 0 个 /Applications/Arduino.app/Contents/Java/hardware/teensy/avr/libraries/Encoder/Encoder.h:69:7:注意:constexpr Encoder::Encoder(const Encoder&) 类编码器 ^ /Applications/Arduino.app/Contents/Java/hardware/teensy/avr/libraries/Encoder/Encoder.h:69:7:注意:候选人需要 1 个参数,提供 0 个 /Applications/Arduino.app/Contents/Java/hardware/teensy/avr/libraries/Encoder/Encoder.h:69:7:注意:constexpr Encoder::Encoder(Encoder&&) /Applications/Arduino.app/Contents/Java/hardware/teensy/avr/libraries/Encoder/Encoder.h:69:7:注意:候选人需要 1 个参数,提供 0 个 调用 'Encoder::Encoder()' 没有匹配的函数

基本上,我相信编译器告诉我它找不到编码器库MIDIEncoder.cpp:8: error: no matching function for call to 'Encoder::Encoder()' 的构造函数,但我不知道为什么。以下是我的库的完整源代码。

MIDIEncoder.h

/*
  MIDIEncoder.h
  A library for creating relative MIDI CC messages from a rotary encoder.

  Created by Paul Williamson, 11 August 2016.

  Project source available at:
  http://github.com/squarefrog/teensy-midi-encoder-box

  Released into the public domain.
*/

#ifndef MIDIEncoder_h
#define MIDIEncoder_h

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

class MIDIEncoder
{
  public:    
  MIDIEncoder(uint8_t pin1, uint8_t pin2, byte midiChannel, byte midiCCNumber);
    byte channel;
    byte ccNumber;

    byte read();

  private:
    unsigned long _lastTurnedTime;
    long _oldPosition;
    Encoder _enc;
};

#endif

MIDIEncoder.cpp

#include "MIDIEncoder.h"
#include <Encoder.h>

const byte incrementValue = 66; // A constant for the start of increment values
const byte decrementValue = 2;  // A constant for the start of decrement values

MIDIEncoder::MIDIEncoder(uint8_t pin1, uint8_t pin2, byte midiChannel, byte midiCCNumber)
{
  channel = midiChannel;
  ccNumber = midiCCNumber;
  _enc = Encoder(pin1, pin2);
  _oldPosition = -999;
  _lastTurnedTime = millis();
}

byte MIDIEncoder::read()
{
  long newPosition = _enc.read();

  // If position hasn't changed, ignore.
  if (newPosition == _oldPosition) {
    return 0;
  }

  // If position is not divisible by 4, ignore.
  if (newPosition % 4 != 0) {
    return 0;
  }

  unsigned long delta = millis() - _lastTurnedTime;
  byte offset = 0;

  // Apply crude acceleration
  if (delta < 100) offset = 4;
  if (delta > 99 && delta < 180) offset = 2;
  if (delta > 179 && delta <= 250) offset = 1;

  _lastTurnedTime = millis();

  // Return MIDI CC value
  if (newPosition > _oldPosition) {
    return incrementValue + offset;
  } else {
    return decrementValue + offset;
  }
}

下面有一些很好的答案。现在我知道要寻找什么了,我找到了this resource,它解释了我在哪里犯了错误。特别看数字3。

【问题讨论】:

    标签: c++ arduino


    【解决方案1】:

    Encoder没有默认构造函数,这里是隐式调用的

    MIDIEncoder::MIDIEncoder(uint8_t pin1, uint8_t pin2, byte midiChannel, byte midiCCNumber) 
        /*Implicit constructor call*/ 
    { 
        //...
    }
    

    您试图将其称为构造函数主体,但到那时“为时已晚”:) 我的意思是,_enc 必须在构造函数主体执行时已经初始化,但 _enc 不能默认初始化,所以编译器会报错。

    这就是构造函数初始化列表的用途:

    MIDIEncoder::MIDIEncoder(uint8_t pin1, uint8_t pin2, byte midiChannel, byte midiCCNumber)
        : _enc(pin1, pin2) //Calls appropriate constructor for _enc, not default
    {
        //...
    }
    

    【讨论】:

    • 哦,快。我以为头声明中的变量名只是一个占位符,用于实现文件。我永远不会想到这一点。
    • 其实头部的声明并没有调用任何构造函数。默认构造函数在 MIDIEncoder 构造函数中隐式调用,以及其他成员变量的构造函数(未另行指定)。
    • 我以为我在用Encoder(pin1, pin2); 调用构造函数。我认为它只是需要以这种方式构造的对象?
    • @squarefrog 不,_enc = Encoder(pin1, pin2); 会 - 如果你的类是默认可构造的,所以你不只是得到一个编译时错误 - 构造一个 temporary @987654329 @ 和 move-assign 给成员。那不是你想要的。出于语义和效率的考虑,任何可以在初始化列表中应该被初始化的东西 - 正如您刚刚看到的,有些东西只能在那里设置。
    【解决方案2】:

    你初始化 _enc 对象太晚了。

    在 MIDIEncoder 构造函数主体 _enc 的开头应该已经创建,因此编译器尝试使用(缺少的)默认构造函数实例化它并失败。

    改为在构造函数初始化列表中初始化它:

    MIDIEncoder::MIDIEncoder(uint8_t pin1, uint8_t pin2, ...) : _enc(pin1, pin2)
    {
    

    实际上,其他变量也是如此——没有理由在构造函数体中对其进行初始化。

    【讨论】:

    • 哦,真的吗?这就是我在其他语言中所习惯的,所以很容易看出我在哪里犯了那个错误。我正在关注使用构造函数的 Arduino 库教程arduino.cc/en/Hacking/LibraryTutorial
    • there is no reason to initialize it inside constructor body. 我知道你的意思,但我会成为令牌书呆子!一个简单的不能初始化体内的成员。一个人只能分配给他们。但是,是的,撇开术语不谈,我同意“没有理由”。任何可以在初始化列表应该中被初始化的东西,即使可以在正文中分配它。这在语义上是正确的,并且在许多情况下更有效。另外,对于像 OP 或 const 成员等对象......初始化是唯一可能的选项。
    • 学一门新语言时欢迎学究气!那么对象、常量和其他任何明显的东西都应该在那里实例化?
    • @squarefrog IMO 任何需要调用适当构造函数的东西,无论所述 ctor 是完全必要的还是比赋值/方法调用更具语义/性能。当然,您可能会发现只有基本或默认构造函数的类,并且需要通过 assign 或 init() 方法完成设置,在这种情况下,您会束手无策。或者他们可能会让你通过 ctor 设置一些属性,但需要在 body 中使用方法来设置其他属性。但是同样,对于您可以设置的任何属性,如果您可以使用构造函数来完成,那通常是最好的 - 假设一个理智的类设计师;-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-16
    • 1970-01-01
    • 2021-09-21
    • 2016-11-23
    相关资源
    最近更新 更多