【问题标题】:C++ basics: unresolved overloaded function typeC++ 基础:未解析的重载函数类型
【发布时间】:2016-10-16 14:24:40
【问题描述】:

我对 C++ 很陌生,可能我遇到了一些幼稚的问题。我知道还有其他类似的问题,但与(在我看来)比我的更复杂的问题有关。 我正在尝试使用 C++ 为 Arduino 制作固件,但我因重载错误而受伤。

我在 cpp 文件中定义了这段代码:

void class1::functionA(void)
{
  object2.functionOfClass2(class1::functionB);
}

class1被初始化为:

class class1
{
 public:
 void functionA(void);
 void functionB(void);
 private:
}

并在编译中给出

no matching function for call to 'class2::functionOfClass2(<unresolved overloaded function type>)'

翻译成实用:

在我的代码中,我在 class1 的成员函数中为 Arduino 库使用 Wire 库,在示例中为 object2class2 分别是 TwoWire 类的 Wire 对象。

我需要在 class1 的成员函数中调用 wire 库。 这个解决方案是上一课的结果,在其中我了解到我不能在非成员函数中调用 class1 的成员函数,因为无法进行非成员函数的实例化,因为该类尚未实例化为对象,编译器不知道如何执行此操作。

但是在成员函数中调用 Wire. 对象,我认为这是可能的。但仔细想想,实际上,当将 class1 成员函数指针传递给 Wire 函数时,编译器不知道要传递给 wire 什么,因此以下内容是错误的:

void class1::functionA(void)
{
  Wire.onRequest(class1::functionB); //wrong
}

onRequest 接受void (*)(void) 函数的位置。

所以尝试

void class1::functionA(void)
{
  Wire.onRequest(&class1::functionB); //wrong
}

错误变成:

错误:没有匹配的函数调用 'TwoWire::onRequest(void (class1::*)())' 候选人是:void TwoWire::onRequest(void (*)())

有办法让这些事情发挥作用吗?如果我说 staticinitializer list,我是不是用正确的关键字走在正确的道路上?

【问题讨论】:

  • 不得不删除我的答案。我不认为这显然是可行的。您需要将您的class1 实例的this 传递给onRequest,如果它接受void (*)()(不允许使用参数),您就不能这样做。一个设计良好的库会改为将onRequest 定义为onRequest(void (*callback)(void*), void* context),而您会将this 传递为context
  • 唯一的方法是,如果你的整个应用程序中只有一个 class1 实例 - 那么你可以无条件地替换这个实例并调用 functionB

标签: c++ arduino overloading overload-resolution


【解决方案1】:

&amp;class1::functionB 是指向成员函数的指针,而不是指向函数的指针。它的类型是void (class1::*)(void),而不是void (*)(void),正如onRequest 方法所期望的那样。这意味着要调用这个指向成员函数的指针,还需要有实例(class1*)。

如果class1 是单例,解决此问题的最简单方法可能是使functionB 成为静态成员或简单的非成员函数(不在任何类中)。

如果class1 不能被假定为单例,那么库必须有一种方法可以将上下文指针(通常是void*)沿函数指针传递,并且该上下文是回调函数的参数。您应该传递 this 作为上下文和指向包装函数的指针,如下所示:

void wrapper_for_class1_functionB(void* context)
{
    static_cast<class1*>(context)->functionB();
}

void class1::functionA(void)
{
    Wire.onRequest(&wrapper_for_class1_functionB, this);
}

【讨论】:

  • 我们的目标不是让它成为单例,事实上数据结构也是在类中定义的。这意味着我不能使用非成员函数,因为它包含对类中定义的结构的数据处理。
  • 然后我尝试了你的建议,看起来很有趣,但这需要再次修改 Wire 库以获取另一个参数。事实上,我得到的错误是一个不匹配的函数。我错过了什么吗?
  • 而且无论如何,“functionB()”中的函数还有其他成员函数需要在.cpp之外调用,所以在主文件中,当对象被创建时。跨度>
  • 如果库没有提供与回调一起传回的上下文参数,那么安装回调的用户代码就不可能知道在哪个上下文中触发了回调,原因很简单回调不接收上下文。而Wire::onRequest 确实没有提供它。您可以做的最好的事情是将上下文(在您的情况下为 this 指针)保存在全局变量中,并确保没有两个实例可以同时等待回调。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多