我有三个 C++ 文件
header1.h
、header2.h
和 main.cpp
。它们如下:
header1.h
,在命名空间lerp
中定义了函数MyNamespace
:
#ifndef HEADER_1_H
#define HEADER_1_H
namespace MyNamespace {
template <typename T>
inline float lerp(float t, T a, T b) {
return (1 - t) * a + t * b;
}
};
#endif
header2.h
,在MyClass
中定义了一个类MyNamespace
,该类有一个名为lerp
的成员函数,它从lerp
调用header1.h
:
#ifndef HEADER_2_H
#define HEADER_2_H
#include "header1.h"
namespace MyNamespace {
struct MyClass {
float x, y, z;
void lerp(float t) {
x = lerp(t, x, 0.f);
// ^^ This results in a compiler error (no matching function for
// call to ‘MyNamespace::MyClass::lerp(float&, float&, float). Why?
// Also, either prefixing this `lerp` with MyNamespace, or changing
// the name of this member function to anything else that's not lerp,
// stops the compiler error from occurring. Why?
}
};
};
#endif
main.cpp
,构造一个类型为 MyClass
的对象并在其上调用 MyClass::lerp()
:
#include "header2.h"
using namespace MyNamespace;
int main()
{
MyClass mc{1, 2, 3};
mc.lerp(4); // results in a compiler error; see the comment in "header2.h"
return 0;
}
当我尝试编译
main.cpp
时,我收到以下关于我在 lerp
中的 MyClass::lerp()
函数中使用 header2.h
的编译器错误:
header2.h: In member function ‘void MyNamespace::MyClass::lerp(float)’:
header2.h:12:17: error: no matching function for call to ‘MyNamespace::MyClass::lerp(float&, float&, float)’
12 | x = lerp(t, x, 0.f);
| ~~~~^~~~~~~~~~~
header2.h:11:10: note: candidate: ‘void MyNamespace::MyClass::lerp(float)’
11 | void lerp(float t) {
| ^~~~
header2.h:11:10: note: candidate expects 1 argument, 3 provided
所以,我的第一个问题是,为什么编译器似乎无法找到
MyNamespace::lerp()
中提供的 header1.h
的定义? 不应该找到吗,因为我们在同一个命名空间 (MyNamespace
) 并且因为 header2.h
包含 header1.h
?
此外,我还观察到,无论是使用
lerp(t, x, 0.f)
显式限定 MyNamespace
,还是通过将成员函数 MyClass::lerp
重命名为其他任何名称,编译器错误都会消失。这是为什么?
为什么编译器似乎无法找到 header1.h 中提供的 MyNamespace::lerp() 的定义?
因为当您编写
x = lerp(t, x, 0.f);
时,搜索查找开始并找到名为lerp
的成员函数,因此查找停止。因此,唯一的候选函数是名为 lerp
的成员函数。由于它与调用参数不兼容,我们收到了上述错误。