C++ 名称查找受模板方法声明的影响

标签 c++ templates overloading name-lookup

我不明白以下 C++ 代码片段中对 static_cast 的需求(使用 GCC-4.7 测试):

#include <cstdio>

class Interface
{
public:
    virtual void g(class C* intf) = 0;

    virtual ~Interface() {}
};

class C
{
public:
    void f(int& value)
    {
        printf("%d\n", value);
    }

    void f(Interface* i)
    {
        i->g(this);
    }

    template <typename T>
    void f(T& t);
    //void f(class Implementation& i);
};

class Implementation : public Interface
{
public:
    Implementation(int value_) : value(value_) {}
    void g(C* intf)
    {
        intf->f(value);
    }

private:
    int value;
};

int main()
{
    C a;
    Implementation* b = new Implementation(1);

    //a.f(b); // This won't work: undefined reference to `void C::f<Implementation*>(Implementation*&)'
    a.f(static_cast<Interface*>(b));

    delete b;

    return 0;
}

如果我省略 static_cast,我会收到链接器错误,因为它想要使用:

template <typename T>
void f(T& t);

而不是:

void f(Interface* i);

另一方面,如果我用以下内容替换模板化方法(在上面的代码片段中注释掉):

void f(class Implementation& i);

然后我就不会收到错误,并且可以看到在运行时调用了“正确”的方法(即:

void f(Interface* i);

)。

为什么模板方法的声明会影响名称查找? 非常感谢,

最佳答案

执行 a.f(b) 的重载解析时,编译器注意到两个事实:

首先,您正在尝试调用f左值类型为 Implementation* .

其次,重载集中有三个函数: C::f(int&)C::f(Interface*)C::f<Implementation*>(Implementation*&) 。请注意 template包含在内是因为它的模板参数可以从调用它的参数中推导出来。

现在编译器开始检查哪个函数最适合“最佳”:

  • C::f(int&)根本不能用这个参数来调用。
  • C::f(Interface*)可以调用,但需要一次标准转换(指向派生的指针 -> 指向基址的指针)
  • C::f<Implementation*>(Implementation*&)可以调用而无需任何转换

因此,该模板非常适合。但是,由于您没有为模板定义实现,因此链接器稍后会出现错误,并显示错误消息:找不到您尝试调用的函数。

关于C++ 名称查找受模板方法声明的影响,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28214060/

相关文章:

java - 如何有效地使用重载和多态性

c++ - 带有 Bash 的 Qt 控制台

c++ - STL 列表访问倒数第二个元素

C++:不确定代码是否是多线程的

c++ - 运算符重载说明

c++ - 重载operator new(),为什么构造函数被调用了两次?

C++使用STL列表,如何将现有列表复制到新列表中

c++ - '{' token c++ 继承问题之前的另一个预期类名

python - 如何在渲染后将数据插入模板? ( Django )

c++ - 从模板化函数返回字符串时,bad_any_cast异常