静态成员函数,同名不同代码,只使用第一个遇到的版本,这是为什么呢?

Static member function, same name, different code, only the first encountered version is used, why is that?

我偶然发现了这种奇怪的行为(在我试图证明如果在头文件中定义了 instance() 函数,Scott Meyers 单例模式将为每个 .cpp 文件生成不同的单例实例之后,但没关系那个)。

它产生什么:

代码产生此输出 - 0 2 4 60 1 2 3 取决于编译顺序 (无论是 test1.cpp 还是 test2.cpp 已先编译).

我的期望:

我希望结果是 0 0 1 2,因为这 2 个函数应该对 2 个独立的静态变量进行操作,即使它们具有相同的名称,更不用说 Foo::foo() 是一个每个编译单元的功能不同。

但是好像test1()test2()调用了Foo::foo()编译时第一次遇到的版本,这让我很意外我。

这是代码:

test1.cpp

static int var = 0;
class Foo {
public:
    static void foo() {
        printf("%d ", var);
        var += 2;             // <--- This is the difference!
    }
};
void test1() {
    Foo::foo();
}

test2.cpp

static int var = 0;
class Foo {
public:
    static void foo() {
        printf("%d ", var);
        var++;                // <--- This is the difference!
    }
};
void test2() {
    Foo::foo();
}

main.cpp

void test1();
void test2();
int main() {
    test2();
    test1();
    test2();
    test1();
    return 0;
}

我的问题

我想我的问题是,为什么编译器会那样做,它是由标准指定的吗,标准对 class 在不同编译单元中的不同实现有何规定,如果它们仅在该编译单元中使用?

由于两个静态函数的命名空间相同(class name 'Foo' 在你的例子中),test1 的编译代码中的函数签名将是完全相同的函数签名测试2。我想根据编译器的不同,你可能会得到一个 warning/error 或者它可能只是跳过编译函数的下一次出现。

因此您的输出结果符合预期。

您违反了“一个定义规则”(第 3.2 节):

Given such an entity named D defined in more than one translation unit, then

  • each definition of D shall consist of the same sequence of tokens; and
  • in each definition of D, corresponding names, looked up according to 3.4 , shall refer to an entity defined within the definition of D, or shall refer to the same entity, after overload resolution (13.3) and after matching of partial template specialization (14.8.3), except that a name can refer to a const object with internal or no linkage if the object has the same literal type in all definitions of D, and the object is initialized with a constant expression (5.19), and the value (but not the address) of the object is used, and the object has the same value in all definitions of D; and
  • in each definition of D, corresponding entities shall have the same language linkage; and
  • in each definition of D, the overloaded operators referred to, the implicit calls to conversion functions, constructors, operator new functions and operator delete functions, shall refer to the same function, or to a function defined within the definition of D; and
  • ...

If the definitions of D satisfy all these requirements, then the program shall behave as if there were a single definition of D.

If the definitions of D do not satisfy these requirements, then the behavior is undefined.

因此,Foo::foo() 在两个文件中应该是相同的方法。 否则,行为未定义。