Why does a function declaration with a const argum

2019-01-14 23:19发布

Take note of the following C++ code:

#include <iostream>
using std::cout;

int foo (const int);

int main ()
{
   cout << foo(3);
}

int foo (int a)
{
   a++;
   return a;
}

Notice that the prototype of foo() takes a const int and that the definition takes an int. This compile without any errors...

Why are there no compilation errors?

4条回答
淡お忘
2楼-- · 2019-01-14 23:32

Top-level const (i.e., that applies to the value that's passed, not something to which it points or refers) affects only the implementation, not the interface, of a function. The compiler ignores it from the interface viewpoint (i.e., the calling side) and enforces it only on the implementation (i.e., code in the body of the function).

查看更多
太酷不给撩
3楼-- · 2019-01-14 23:35
int foo (const int a)
{
   a++;
   return a;
}

That'll throw an error during compiling.

查看更多
Juvenile、少年°
4楼-- · 2019-01-14 23:47

Because it doesn't matter to the caller of the foo function whether foo modifies its copy of the variable or not.

Specifically in the C++03 standard, the following 2 snippets explain exactly why:

C++03 Section: 13.2-1

Two function declarations of the same name refer to the same function if they are in the same scope and have equivalent parameter declarations (13.1).

C++03 Section: 13.1-3

Parameter declarations that differ only in the presence or absence of const and/or volatile are equivalent. Only the const and volatile type-specifiers at the outermost level of the parameter type specification are ignored in this fashion; const and volatile type-specifiers buried within a parameter type specification are significant and can be used to distinguish overloaded function declarations.

查看更多
唯我独甜
5楼-- · 2019-01-14 23:52

As others have explained, the Standard says it's ok, and that the compiler can afford to be lenient about enforcing this because it doesn't affect the caller, but nobody's answered why the compiler should choose to be lenient. It's not particularly lenient in general, and a programmer who's just been looking at the interface then dives into the implementation may have it in the back of their mind that a parameter is const when it's not or vice versa - not a good thing.

This leniency allows implementation changes without modifying headers, which using traditional make tools triggers recompilation of client code. This can be a serious issue in enterprise scale development, where a non-substantive change in a low-level header (e.g. logging) can force rebuilding of virtually all objects between it and the applications... wasting thousands of hours of CPU time and delaying everyone and everything waiting on the builds.

So, it's ugly, but a practical concession.

I've also answered another similar question which looks at why overloading of f(const T) and f(T) isn't allowed - may be of interest to anyone reading this - Top-level const doesn't influence a function signature

查看更多
登录 后发表回答