【问题标题】:C++: Confusion over function overloading and order of declarationC++:对函数重载和声明顺序的混淆
【发布时间】:2011-07-27 18:25:21
【问题描述】:

我意识到 C++ 继承了 C 的许多要求,其中之一是编译器无法识别全局函数,除非它以前遇到过该函数的原型或定义。

这也会影响 C++ 函数重载。如果一个函数调用有多个候选者,并且编译器尚未看到它的原型/定义,则“正确”候选者将不会包含在选择过程中。

考虑:

void foo(int v)
{
    cout << "Int version" << endl;
}

template <class T>
void call_foo(const T& v)
{
    foo(v);
}

void foo(const std::string& v)
{
    cout << "Overload for string" << endl;
}

这里,对call_foo(std::string("abc")) 的调用将导致编译器错误,即使std::stringfoo 过载。问题是函数模板call_foo 是在编译器看到重载之前定义的

但是,这似乎不适用于全局运算符重载。我们定期重载 std::ostream&amp; operator &lt;&lt; (std::ostream&amp; os, const T&amp;); 以使我们的自定义类型与 C++ ostream 兼容。编译器会选择正确的重载,而不管运算符重载函数是在哪里定义的。

例如:

struct Bar { };

template <class T>
void dispatch(const T& v)
{
    std::cout << v << std::endl;
}

std::ostream& operator << (std::ostream& os, const Bar& b)
{
    os << "Outputting Bar...";
    return os;
}

这里,如果我们调用dispatch(Bar()),编译器会调用正确的重载并输出Outputting Bar...

因此,在选择运算符重载的候选函数时,C++ 标准似乎允许更高级的行为。

我的问题是,为什么不将此能力扩展到常规函数重载?我意识到需要与 C 向后兼容,但这实际上并没有任何关系,因为一旦你编写了函数重载,你就不是在编写 C 程序了。

【问题讨论】:

  • 第二个foo 不是特化,它只是另一个重载名称 foo 的函数。
  • 我不明白您的operator&lt;&lt; 示例,因为它与您的第一个示例无法比较。没有调度模板,只有各种重载。
  • @Gman,关键是如果调度模板被定义之前写入operator&lt;&lt;的重载,当你调用调度模板时,无论如何都会选择正确的重载.但这不会发生在常规函数中。
  • @Channel:确实如此。再说一次,你的例子没有可比性。如果有一个通用的operator&lt;&lt; 然后是一个通用的调度程序,则不会通过调度程序找到进一步的重载,就像您的示例一样。但是标准库中既没有通用的operator&lt;&lt;,也没有通用的operator&lt;&lt; 调度程序。正如您的评论所暗示的,添加通用调度程序只是等式的一半。您仍然缺少一个可以调用的通用函数。
  • @Gman,好的,我稍微扩展了问题以详细说明我在说什么。请注意,调度函数是在重载之前定义的。但是编译器无论如何都会做正确的事情。但是,这似乎只适用于运算符重载 - 而不是常规函数重载。

标签: c++ function overloading


【解决方案1】:

首先,编译器不需要在定义时查看 实践超载解决方案;一个声明就足够了。二、 问题比您似乎意识到的要复杂得多。在你的功能 模板call_foofoo 是一个依赖名称,因为它用于 取决于实例化类型的上下文。这意味着它 将被查找两次,一次在模板所在的位置 定义,第二次实例化模板。这 然而,第二次查找纯粹是 ADL;它不会找到声明 由 ADL 带来。在您的情况下,您想要的 foo 在全球范围内 命名空间,但是当使用std::string 调用它时,唯一的命名空间 ADL 认为是std::

在您的第二个示例中,Bar 位于全局命名空间中,因此在 将考虑实例化时的全局命名空间。 (请注意,如果 dispatch 不是模板,则不会是 考虑。)

【讨论】:

    猜你喜欢
    • 2022-01-16
    • 2022-01-13
    • 2023-03-12
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 2015-04-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多