gpt4 book ai didi

C++:对函数重载和声明顺序的混淆

转载 作者:搜寻专家 更新时间:2023-10-31 00:45:25 25 4
gpt4 key购买 nike

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

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

考虑:

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"))将导致编译器错误,即使存在 foo 的重载也是如此对于 std::string .问题是函数模板 call_foo 编译器看到重载之前定义。

但是,这似乎不适用于全局运算符重载。我们经常重载 std::ostream& operator << (std::ostream& os, const T&);使我们的自定义类型与 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 程序了。

最佳答案

首先,编译器在编译时不需要查看定义实践过载决议;一份声明就足够了。第二,问题比您似乎意识到的要复杂得多。在你的函数中template call_foo, foo 是一个从属名,因为它用在取决于实例化类型的上下文。这意味着它将被查找两次,一次是在模板所在的位置定义,第二次实例化模板。这然而,第二次查找纯粹是 ADL;它不会找到声明由 ADL 引入。在你的情况下,你想要的 foo 在全局命名空间,但是当用 std::string 调用它时,唯一的命名空间ADL 考虑的是 std::

在你的第二个例子中,Bar 在全局命名空间中,所以声明在将考虑实例化时的全局命名空间。(请注意,如果 dispatch 不是模板,它就不会是考虑过。)

关于C++:对函数重载和声明顺序的混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6849286/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com