7

请注意,以下两个函数具有相同的类型和签名:

void foo1(int t) {} // foo1 has type 'void(*)(int)', and signature '(*)(int)'
void foo2(const int t) {} // Also type 'void(*)(int)', signature '(*)(int)'

const不是函数类型或函数签名的一部分)。同样,返回类型上的修饰符(constvolatile)不会影响函数类型或函数签名。

但是,在函数定义本身(未显示)中,命名变量t确实保持constfoo2.

有许多 StackOverflow 问题讨论了为什么函数的返回类型不被视为函数签名的一部分(用于重载解析)。

但是,我找不到任何 StackOverflow 问题来询问为什么参数修饰符(constvolatile)不是函数类型或签名的一部分。另外,我直接查看了 C++11 标准文档,发现很难解开。

const参数修饰符(即和volatile)不是函数类型或签名的一部分这一事实背后的基本原理是什么?

附录为了清楚起见,从下面 R.MartinhoFernandes 的回答中,我应该澄清在 C++ 中(我认为)参数修饰符const,并且如果它们是顶级volatile修饰符,则仅作为函数类型/签名的一部分被忽略- 请参见下面的答案。

4

1 回答 1

12

参数修饰符(即 const 和 volatile)不是函数类型或签名的一部分这一事实背后的基本原理是什么?

void foo(int)从调用者的角度来看,和之间没有区别void foo(int const)。无论您传递给它的任何内容都不会被修改,无论修饰符如何:该函数将获得一个副本。

从实现者的角度来看,唯一的区别是void foo(int x)你可以在正文中进行变异x(即你的本地副本),但你不能x使用void foo(int const x).

C++ 承认这两种观点。通过做出两个声明void foo(int);void foo(int const);声明相同的函数来确认调用者的观点。通过允许您将函数声明为void foo(int x);但将其定义为void foo(int const x) { /*...*/ }要确保不会意外分配给参数,从而承认了实现者的观点。

请注意,这仅适用于 top-level const,即const适用于整个类型。在诸如int const&orint const*之类的修饰符仅适用于类型的一部分,作为“指向 (const (int)) 的指针”,因此它不是顶级的const。然而int *constconst再次适用于整个类型,如“const(指向(int))”。

于 2012-12-04T16:12:58.783 回答