Не все объявления функций могут быть перегружены. Здесь указаны те, которые нельзя перегрузить. Программа плохо сформирована, если она содержит два таких неперегружаемых объявления в одной и той же области видимости. [ Note: Это ограничение применяется к явным объявлениям в области видимости, а также между такими объявлениями и объявлениями, сделанными через using-declaration. Это не относится к наборам функций, созданным в результате поиска имени (например, из-за using-directives) или разрешения перегрузки (например, для операторских функций). ] — end note
Некоторые объявления функций не могут быть перегружены:
Объявления функций, которые различаются только типом возвращаемого значения, exception specificationили и тем , и другим, не могут быть перегружены.
Объявления функций-членов с тем же именем и одинаковыми именами parameter-type-list не могут быть перегружены, если любое из них является static объявлением функции-члена ([class.static]). Точно так же объявления шаблонов функций-членов с тем же именем, одним и тем же списком типов-параметров и одними и теми же списками параметров шаблона не могут быть перегружены, если какое-либо из них является static объявлением шаблона функции-члена. Типы неявных параметров объекта, созданных для функций-членов с целью разрешения перегрузки ([over.match.funcs]), не учитываются при сравнении списков типов параметров для применения этого правила. Напротив, если нет static объявления функции-члена среди набора объявлений функций-членов с тем же именем и одним и тем же списком типов-параметров, то эти объявления функций-членов могут быть перегружены, если они различаются по типу параметра неявного объекта. [ Example: Следующее иллюстрирует это различие:
class X { static void f(); void f(); // ill-formed void f() const; // ill-formed void f() const volatile; // ill-formed void g(); void g() const; // OK: no static g void g() const volatile; // OK: no static g };
— end example ]
Объявления функций-членов с тем же именем иparameter-type-list такими же, а также объявления шаблонов функций-членов с тем же именем, одним и тем же списком типов-параметров и одними и теми же списками параметров шаблона не могут быть перегружены, если любой из них, но не все, имеет ref-qualifier([dcl.fct]). [ Example:
class Y { void h() &; void h() const &; // OK void h() &&; // OK, all declarations have a ref-qualifier void i() &; void i() const; // ill-formed, prior declaration of i // has a ref-qualifier };
— end example ]
[ Note: Как указано в [dcl.fct], объявления функций с эквивалентными объявлениями параметров объявляют одну и ту же функцию и поэтому не могут быть перегружены:
Объявления параметров, которые отличаются только использованием эквивалентных typedef «типов», эквивалентны. A typedef - это не отдельный тип, а только синоним другого типа ([dcl.typedef]). [ Example:
typedef int Int; void f(int i); void f(Int i); // OK: redeclaration of f(int) void f(int i) { /* ... */ } void f(Int i) { /* ... */ } // error: redefinition of f(int)
— end example ]
С другой стороны, перечисления относятся к разным типам и могут использоваться для различения объявлений перегруженных функций. [ Example:
enum E { a }; void f(int i) { /* ... */ } void f(E i) { /* ... */ }
— end example ]
Объявления параметров, которые отличаются только указателем * от массива [] , эквивалентны. То есть объявление массива корректируется, чтобы стать объявлением указателя ([dcl.fct]). Только второе и последующие измерения массива имеют значение в параметрах types ([dcl.array]). [ Example:
int f(char*); int f(char[]); // same as f(char*); int f(char[7]); // same as f(char*); int f(char[9]); // same as f(char*); int g(char(*)[10]); int g(char[5][10]); // same as g(char(*)[10]); int g(char[7][10]); // same as g(char(*)[10]); int g(char(*)[20]); // different from g(char(*)[10]);
— end example ]
Объявления параметров, которые отличаются только тем, что один является типом функции, а другой - указателем на тот же тип функции, эквивалентны. То есть тип функции корректируется, чтобы стать указателем на функцию type ([dcl.fct]). [ Example:
void h(int()); void h(int (*)()); // redeclaration of h(int()) void h(int x()) { } // definition of h(int()) void h(int (*x)()) { } // ill-formed: redefinition of h(int())
— end example ]
Объявления параметров, которые отличаются только наличием или отсутствием const и / или volatile эквивалентны. То есть, const и volatile типа-спецификаторы для каждого типа параметра игнорируется при определении того, какие функции объявляются, определяются или вызываются. [ Example:
typedef const int cInt; int f (int); int f (const int); // redeclaration of f(int) int f (int) { /* ... */ } // definition of f(int) int f (cInt) { /* ... */ } // error: redefinition of f(int)
— end example ]
Только const и volatile на самом внешнем уровне спецификации типа параметра игнорируется таким образом спецификаторы типа; const а volatile спецификаторы типа, скрытые в спецификации типа параметра, имеют важное значение и могут использоваться для различения объявлений перегруженных функций.123 В частности, для любого типа T«указатель на T», «указатель на const T» и «указатель на volatile T» считаются отдельными типами параметров, как и «ссылка на T», «ссылка на const T» и «ссылка на volatile T».
Два объявления параметров, которые различаются только аргументами по умолчанию, эквивалентны. [ Example: Учтите следующее:
void f (int i, int j); void f (int i, int j = 99); // OK: redeclaration of f(int, int) void f (int i = 88, int j); // OK: redeclaration of f(int, int) void f (); // OK: overloaded declaration of f void prog () { f (1, 2); // OK: call f(int, int) f (1); // OK: call f(int, int) f (); // Error: f(int, int) or f()? }
— end example ]
— end note ]
Когда тип параметра включает в себя тип функции, например, в случае типа параметра , который представляет собой указатель на функцию, то const и volatile типа спецификаторы на внешнем уровне спецификаций типа параметра для внутреннего типа функции также игнорируются.