问题是参考 this ,这是在不久前发布的。
尽管OP很乐意接受解决了他的问题的答案,但我对于为什么编译器给出了看似错误的错误的细节感到有点兴趣。
下面是我创建的一个小代码示例,用于演示相同的内容:
class YourClass
{
};
class YourClass2
{
};
class MyClass
{
public:
void doSomething(YourClass2 obj)
{
//Nothing more Interesting to do
}
};
int main()
{
YourClass *ptr = new YourClass();
MyClass obj;
obj.doSomething(ptr);
return 0;
}
使用 GCC(4.3.4)编译 this 会产生一个看似奇怪的错误结果:
prog.cpp: In function ‘int main()’:
prog.cpp:23: error: no matching function for call to ‘MyClass::doSomething(YourClass*&)’
prog.cpp:13: note: candidates are: void MyClass::doSomething(YourClass2)
所以问题是:
为什么编译器会处理呼叫,
obj.doSomething(ptr);
调用带有原型的函数,
MyClass::doSomething(YourClass*&)
而不是
MyClass::doSomething(YourClass*)
这似乎是一个明显的例子。
答案 0 :(得分:6)
首先,请注意表达式 ptr
(不是变量 ptr
)的类型为YourClass *&
。这个很重要;它是引用类型可以工作的唯一方式(否则,当您执行YourClass *&x = ptr
时,您将引用副本,这也是YourClass *&x = (ptr + 1)
失败的原因)。因此,编译器开始搜索具有MyClass::doSomething(YourClass *&)
的函数。
当然,此调用可以匹配原型MyClass::doSomething(YourClass *)
。它也可以匹配MyClass::doSomething(const YourClass *)
或许多其他人。可能存在数十个(或者,具有多个参数,容易数百或数千个)可能与此调用匹配的原型;然而,没有人能找到。
因此编译器放弃了,并给出了错误。在错误中,而不是列出每个理论上可能的匹配,它引用了一个最接近它最初寻找的原型;也就是MyClass::doSomething(YourClass *&)
。
答案 1 :(得分:4)
正如其他人所说,编译器正试图提供帮助,并且可能让您感到困惑。让我们从最简单的错误开始:
错误:没有匹配函数来调用
obj.doSomething(ptr)
虽然错误消息是正确的,但它提供的信息非常有限。在这个例子中,代码很容易遵循,但考虑更复杂的代码。你阅读了错误信息,你可能会想...... 什么是obj?,什么是ptr?所以它试图帮助你并告诉你obj
是什么:
错误:没有匹配函数来调用'MyClass :: doSomething(ptr)'
嗯,那更好,它告诉你至少在你需要查找重载的类中,但是考虑到类是std::ostream
而函数operator<<
...只是过多的重载,仍然是ptr
的类型是什么?所以它向前移动并试图描述参数:参数是类型为YourClass*
的左值 ...我已经看到过去产生的那种错误信息:
错误:没有匹配函数来调用'MyClass :: doSomething',它将
YourClass*
左值作为参数。
好的,所以错误报告已经完成。现在认为该函数可能有更多的参数,并且错误消息可以变成一个复杂的野兽(想象一下5的类型XXX的左值列表和一个类型为YYY的左值和......“)。接下来的事情是使错误消息的语法同样精确(参数的左值 - 的重要性,或 rvalue - 的重要性,因此必须存在一条信息)。所以它再次重写错误消息:
错误:没有匹配函数来调用'MyClass :: doSomething(YourClass *&amp;)'
问题是你试图将其解释为函数签名,但它更像是函数调用的描述。
错误消息未在标准中定义,并且它们在一个编译器与另一个编译器之间存在差异,即使在同一编译器中也是从一个版本到另一个版本。在一天结束时,您需要学习阅读错误消息及其含义。
答案 2 :(得分:1)
编译器正试图提供帮助。
MyClass::doSomething(YourClass*&)
这并没有命名任何函数:代码中没有与此匹配的函数。
YourClass*&
是您尝试传递给名为MyClass::doSomething
的函数的参数的类型:参数(ptr
)是左值,由{{在错误中表示1}}。
编译器需要某种方法来区分左值参数和右值参数,以便为您提供尽可能多的有用诊断信息;这是一种简洁的方法。
答案 3 :(得分:0)
编译器不需要生成对您有意义的消息。它需要告诉您代码中存在错误。现在它打印的消息是由编译器决定的。标准没有说明它应该打印什么消息,什么不打印。当编译器输出错误消息时,我认为该错误消息可能是好的/有用的,也可能是坏的/无用的,但不是“错误的”。