1

重新定义是否意味着我们正在尝试定义一个已经定义的实体。这个问题出现在以下代码示例中:

int a=5;

int main()
{
    int a=3;//redefinition? I think no, because `int a` denote an entity different from the global "a"
}

还有一个例子:

int foo(){ return 1; }

int main()
{
    int foo();
    int a=foo();//Now a is 1
}

我们不能foo()main()函数体内定义刚刚声明的函数,但如果可以的话,它会是一个重新定义吗?

4

5 回答 5

4

局部变量可能会影响全局变量,这就是::范围解析运算符的用途

#include <iostream>
using namespace std;

int a=5;

int main()
{
    int a=3;

    cout << a; // 3
    cout << ::a; // 5
}

所以这里没有ODR问题。

至于第二个例子,另一个函数内部的函数声明(当它不会被最烦人的解析混淆时),我推荐这个问题:函数内部的函数声明是否有用?

而且:不,你不能在 main() 中重新定义你的函数。您可以重新声明它(即使使用不同的参数,从而声明一个新函数),但这并不意味着您可以这样定义它。

我建议阅读wiki 页面的精彩摘录:

简而言之,ODR 指出:

  • 在任何翻译单元中,模板、类型、函数或对象只能有一个定义。其中一些可以有任意数量的声明。定义提供了一个实例。

  • 在整个程序中,一个对象或非内联函数不能有多个定义;如果使用一个对象或函数,它必须只有一个定义。您可以声明一个从未使用过的对象或函数,在这种情况下您不必提供定义。在任何情况下都不能有一个以上的定义。

  • 有些东西,比如类型、模板和外部内联函数,可以在多个翻译单元中定义。对于给定的实体,每个定义必须相同。不同翻译单元中的非外部对象和函数是不同的实体,即使它们的名称和类型相同。

编译器必须诊断出一些违反 ODR 的情况。其他违规,特别是跨越翻译单元的违规,不需要诊断。1

于 2014-05-15T11:39:53.050 回答
0

No. int a = foo();orint a = 3;里面main(),是一个新的变量,也叫a

重新定义是尝试重新定义相同的变量,例如:

int a = 5;
int a = 6;

int foo();

不是一个定义。这是一个宣言。函数定义包括{ }.

于 2014-05-15T11:37:49.347 回答
0

重新定义在某种程度上是导致编译器时错误的原因。例如:

int a;
bool a;

或者

void f();
int f;

在您的情况下,没有编译器时错误。这是关于名称隐藏、范围和解析规则的。

int a = 5;
{
  int a = 6; //because of { } internal a is in other scope and can be defined without error
  int b = a; //b == 6
}
int b = a; //b == 5

在最后一种情况下,您有两个不同的“a”,每个都在自己的程序范围内。在一个程序中,如果您使用诸如“a”之类的名称,则该名称后面只有一个实体。如果编译器在不同变体之间找不到“a”的最佳匹配,则会重新定义和错误。

于 2014-05-15T11:44:02.030 回答
0

不,在处理重新定义时,记住 SCOPE 很重要。它仅适用于在 SAME SCOPE 中定义的两个同名变量

在示例 1 中,第二个 a 是 LOCAL SCOPE 并且是函数的局部变量。因此,这是在退出函数体之前查看和引用的 a

于 2014-05-15T11:39:46.070 回答
0

第一个不是因为范围不同而重新定义,就像你想象的那样。

第二个是重新声明,但是可以根据需要多次重新声明某些内容,尽管这个笑话会随着重复而变得陈旧。

如果您允许在函数内部定义函数,则可以编写所有语义,因为还没有这样的语义(除了 lambdas)。
对于这样做的人,请查看 GCC C 编译器、“嵌套函数”和“语句表达式”。

无论如何,由于单一定义规则,重新定义将是一个错误。

于 2014-05-15T11:41:08.790 回答