冲突的声明
来自 cppreference.com
除非另有说明,否则两个声明不能(重新)引入相同的实体。如果存在此类声明,则程序是格式错误的。
目录 |
[编辑] 对应声明
如果两个声明(重新)引入了相同的名称,都声明了构造函数,或者都声明了析构函数,则它们对应,除非
- 其中一个是 using 声明,
- 一个声明类型(不是 typedef 名称),而另一个声明变量、非静态数据成员(非 匿名联合 的成员)、枚举器、函数或函数模板,或者
- 每个都声明一个函数或函数模板,并且它们没有声明对应的重载。
[编辑] 对应函数重载
如果两个 函数声明 都声明满足以下所有条件的函数,则它们声明对应重载
|
(自 C++20 起) |
- 如果它们都是非静态成员函数,则它们还需要满足以下要求之一
|
(自 C++23 起) |
- 它们的对象参数具有相同的类型。
[编辑] 对应函数模板重载
如果两个 函数模板声明 都声明满足以下所有条件的函数模板,则它们声明对应重载
|
(自 C++20 起) |
- 如果它们都是非静态成员函数模板,则它们还需要满足以下要求之一
|
(自 C++23 起) |
- 它们的对象参数具有等效的类型。
struct A { friend void c(); // #1 }; struct B { friend void c() {} // corresponds to, and defines, #1 }; typedef int Int; enum E : int { a }; void f(int); // #2 void f(Int) {} // defines #2 void f(E) {} // OK, another overload struct X { static void f(); void f() const; // error: redeclaration void g(); void g() const; // OK void g() &; // error: redeclaration void h(this X&, int); void h(int) &&; // OK, another overload void j(this const X&); void j() const &; // error: redeclaration void k(); void k(this X&); // error: redeclaration };
[编辑] 同一实体的多个声明
如果声明的名称是 _ 并且它声明了以下内容,则该声明是名称无关的 |
(自 C++26 起) |
除非另有说明,否则如果满足以下所有条件,则两个实体的声明声明同一个实体,考虑到未命名类型的声明会出于链接目的引入其 typedef 名称 和 枚举名称(如果存在)
|
(自 C++26 起) |
- 满足以下条件之一
- 它们出现在同一个翻译单元中。
(自 C++20 起) |
- 它们都声明具有 外部链接 的名称。
实体或 typedef 名称 X
的声明是 X
的重新声明,如果可以从它访问 X
的另一个声明。
[编辑] 限制
如果实体 E
的任何两个声明违反了以下相应限制,则程序是格式错误的
- 如果一个声明
E
为变量,则另一个也必须将E
声明为相同类型的变量。 - 如果一个声明将
E
声明为一个 函数,则另一个声明也必须将E
声明为相同类型的函数。 - 如果一个声明将
E
声明为一个 枚举器,则另一个声明也必须将E
声明为一个枚举器。 - 如果一个声明将
E
声明为一个 命名空间,则另一个声明也必须将E
声明为一个命名空间。 - 如果一个声明将
E
声明为一个 类类型,则另一个声明也必须将E
声明为一个类类型。 - 如果一个声明将
E
声明为一个 枚举类型,则另一个声明也必须将E
声明为一个枚举类型。 - 如果一个声明将
E
声明为一个 类模板,则另一个声明也必须将E
声明为一个具有等效模板参数列表的类模板(参见 函数模板重载)。 - 如果一个声明将
E
声明为一个 函数模板,则另一个声明也必须将E
声明为一个具有等效模板参数列表和类型的函数模板。
|
(自 C++11 起) |
|
(自 C++14 起) |
|
(自 C++20 起) |
在所有类型调整之后(在此期间,typedef 将被其定义替换)比较类型。数组对象的声明可以指定数组类型,这些类型因是否存在主数组边界而异。如果两个声明都无法从另一个声明访问,则不需要诊断。
void g(); // #1 void g(int); // OK, different entity from #1 (they do not correspond) int g(); // Error: same entity as #1 with different type void h(); // #2 namespace h {} // Error: same entity as #2, but not a function
如果声明具有 内部链接 的名称的声明 H
先于另一个翻译单元 U
中的声明 D
,并且如果它出现在 U
中,则会声明与 D
相同的实体,则程序是格式错误的。
[编辑] 潜在冲突的声明
如果两个声明对应但声明不同的实体,则它们潜在冲突。
如果在任何范围内,一个名称绑定到两个潜在冲突的声明 A
和 B
,B
不是名称独立的(自 C++26 起),并且 A
先于 B
,则程序是格式错误的
void f() { int x, y; void x(); // Error: different entity for x int y; // Error: redefinition } enum { f }; // Error: different entity for ::f namespace A {} namespace B = A; namespace B = A; // OK, no effect namespace B = B; // OK, no effect namespace A = B; // OK, no effect namespace B {} // Error: different entity for B void g() { int _; _ = 0; // OK int _; // OK since C++26, name-independent declaration _ = 0; // Error: two non-function declarations in the lookup set } void h () { int _; // #1 _ ++; // OK static int _; // Error: conflicts with #1 because // static variables are not name-independent }
[编辑] 缺陷报告
以下行为更改缺陷报告已追溯应用于先前发布的 C++ 标准。
DR | 应用于 | 发布时的行为 | 正确的行为 |
---|---|---|---|
CWG 279 (P1787R6) |
C++98 | 不清楚未命名的类或枚举是否可以 如果它具有用于链接目的的 typedef 名称,则可以重新声明 |
它可以重新声明 |
CWG 338 (P1787R6) |
C++98 | 不清楚未命名的枚举是否可以 如果它具有枚举器作为链接目的的名称,则可以重新声明 |
它可以重新声明 |
CWG 1884 (P1787R6) |
C++98 | 适用于多个的限制 同一实体的声明不清楚 |
已澄清 |