Правило единого определения означает, что каждая перегруженная функция должна быть определена один раз. Так что нет никакого противоречия. Каждая перегруженная функция в некотором роде отличается, например, количеством или типами параметров, квалификаторами c / v присутствия или отсутствия (в объявлениях параметров или самих функциях-членах класса) и т. Д.
Иногда начинающие считают, например, эти объявления функций объявлениями перегруженных функций
void f( int a[100] );
void f( int a[10] );
void f( int a[] );
void f( int *a );
Однако компилятор неявно настраивает параметр типа массива на указатель типа элемента массива.
Вы можете включить все эти (избыточные) объявления в вашу программу, но должны определить функцию только один раз.
Таким образом, в приведенных выше объявлениях объявляется одна и та же функция, параметры которой корректируются компилятором для типа int *
.
Учтите, что эти объявления функций объявляют две перегруженные функции
void f( int *a );
void f( const int *a );
(здесь сам указатель не является константой, это данные, на которые указывает указатель, является константой)
пока эти два объявления
void f( int x );
void f( const int x );
объявляют одну и ту же функцию, потому что спецификатор const отбрасывается, когда компилятор определяет, перегружены ли функции или являются одинаковыми.
Такая же путаница может возникнуть, когда параметр функции имеет тип функции. Например
void f( void g() );
void f( void ( *g )() );
Опять же, компилятор неявно настраивает параметр типа функции для указания на функцию.
Вот демонстрационная программа
#include <iostream>
void f( void g() );
void f( void ( *g )() );
void g() { std::cout << "Hello Philippa Richter\n"; }
void f( void g() )
{
g();
}
int main()
{
f( g );
}
Его вывод
Hello Philippa Richter
Обратите внимание, что функция f
определяется один раз, хотя она объявляется три раза, включая объявление, которое одновременно является ее определением.