I am learning the basics of C++ and OOP in my university now. I am not 100% sure how a function pointer works when assigning functions to them. I encountered the following code:
void mystery7(int a, const double b) { cout << "mystery7" << endl; }
const int mystery8(int a, double b) { cout << "mystery8" << endl; }
int main() {
void(*p1)(int, double) = mystery7; /* No error! */
void(*p2)(int, const double) = mystery7;
const int(*p3)(int, double) = mystery8;
const int(*p4)(const int, double) = mystery8; /* No error! */
}
From my understanding, the p2
and p3
assignments are fine as the function parameters types match and const-ness is correct. But why don't the p1
and p4
assignments fail? Shouldn't it be illegal to match const double/int to non-const double/int?
According to the C++ Standard (C++ 17, 16.1 Overloadable declarations)
(3.4) — Parameter declarations that differ only in the presence or absence of const and/or volatile are equivalent. That is, the const and volatile type-specifiers for each parameter type are ignored when determining which function is being declared, defined, or called.
So in the process of determining of the function type the qualifier const for example of the second parameter of the function declaration below is discarded.
void mystery7(int a, const double b);
and the function type is void( int, double )
.
Also consider the following function declaration
void f( const int * const p );
It is equivalent to the following declaration
void f( const int * p );
It is the second const that makes the parameter constant (that is it declares the pointer itself as a constant object that can not be reassigned inside the function). The first const defines the type of the pointer. It is not discarded.
Pay attention to that though in the C++ Standard there is used the term "const reference" references themselves can not be constant opposite to pointers. That is the following declaration
int & const x = initializer;
is incorrect.
While this declaration
int * const x = initializer;
is correct and declares a constant pointer.