【问题标题】:Function falls completely off the candidate list if it takes a pointer to the class如果函数需要一个指向该类的指针,则该函数完全脱离候选列表
【发布时间】:2020-09-02 08:38:43
【问题描述】:

为什么我不能有一个与成员函数同名的非成员函数,如果它也恰好带有指向类的指针?

这不能编译:

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);
  • 哇!我希望编译器会告诉我。我会接受这个作为答案。
  • 重载适用于在同一范围内定义的函数。 API 有两个成员函数名称configure,它们是重载的。全局命名空间中的其他东西没有定义在与其他两个相同的范围内,因此编译器不会查找它。编译器可能会猜到您打算使用全局函数,但是当有六个全局函数时,或者当您不打算使用全局函数并且只是简单地使用全局函数时,您会发现一个非常烦人的警告输入错误的参数之一。

标签: c++ name-lookup


【解决方案1】:

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

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

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

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

如果我 [...] 让它接受一个引用而不是指针,那么它就会突然存在,一切都很好。

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

【讨论】:

    【解决方案2】:

    尝试在成员函数中调用configure 时,在类范围(即成员函数)中找到名称configure,然后name lookup 停止,更远的范围(全局范围)不会检查;全局configure 找不到,被成员函数隐藏了。

    名称查找如下所述检查范围,直到找到至少一个任何类型的声明,此时查找停止并且不再检查范围。

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

    【讨论】:

      【解决方案3】:

      试试

      ::configure(this, cfg.value);
      

      【讨论】:

        猜你喜欢
        • 2014-01-02
        • 1970-01-01
        • 2023-03-22
        • 1970-01-01
        • 2020-01-12
        • 1970-01-01
        • 2021-12-21
        • 2014-09-24
        • 1970-01-01
        相关资源
        最近更新 更多