如果函数采用指向类的指针,则函数将完全脱离候选列表

Function falls completely off the candidate list if it takes a pointer to the class

本文关键字:函数 列表 候选 指针 如果      更新时间:2023-10-16

为什么我不能有一个与成员函数同名的非成员函数,如果它也碰巧需要一个指向该类的指针?

这不会编译:

struct FooConfig{ int value; };
struct BarConfig{ int value; };
class Api
{
void configure(const FooConfig& cfg);
void configure(const BarConfig& cfg);
};
// helper
static void configure(Api* self, int value)
{
// Actual impl
}
void Api::configure(const FooConfig& cfg)
{
configure(this, cfg.value);
}
void Api::configure(const BarConfig& cfg)
{
configure(this, cfg.value);
}

Gcc 和 Clang 都在骗我,说没有一个名为 configure 的函数需要 2 个参数。

有趣的部分来了:

如果我只是用 self 指针重命名帮助器函数,或者让它接受引用而不是指针,那么它就会突然出现,一切都很好。

AFAIK,与成员函数的巧合相似性在名称查找中无关紧要。我在愚弄C++吗?

在重载解析选择最佳可行函数之前,会形成一组候选函数,专门匹配被调用方的名称。为此,使用名称查找过程。

表达式configure(this, cfg.value)是类成员函数作用域内的非限定调用,为此,名称查找过程将首先在该功能块本身(首次使用之前(搜索声明,如果未找到,则遍历类及其基类,只有在仍然找不到的情况下,它才会访问封闭命名空间。也就是说,当使用搜索范围的有序层次结构时,它将在第一个声明处停止。

在上述过程的第 2 阶段,名称 loopkup 过程找到Api::configure的两个过度,并形成过载解决的候选集。由于两者都不采用两个参数,因此编译器会正确诊断错误。

要强制从全局命名空间使用该函数,请使用::configure(this, cfg.value)。这指示应为configure的声明搜索哪个命名空间。

如果我[...]让它采用引用而不是指针,那么它突然出现,一切都很好。

这是不可能的,因为这不会影响名称查找过程。但是,更改名称确实如此。

当尝试在成员函数中调用configure时,在类范围(即成员函数(中找到名称configure,然后名称查找停止,不会检查进一步的作用域(全局作用域(;找不到全局configure,它被成员函数隐藏。

名称查找按如下所述检查作用域,

直到找到至少一个任何类型的声明,此时查找停止,不再检查其他作用域。

作为解决方法,您可以将全局指定为::configure(this, cfg.value);

尝试

::configure(this, cfg.value);