为什么Google Test Sample会将测试放在匿名名称空间中?

Dan*_*arb 6 c++ unit-testing googletest

这不是未命名名称空间优于静态名称优势吗? 将其标记为重复之前,请仔细阅读该问题。我不是在问为什么使用未命名的名称空间而不是静态名称空间!
我问,为什么将Google测试放在未命名的命名空间中?这是Google测试遵循的一些约定吗?如果是,为什么?无论它们是否在未命名的名称空间中,测试都可以正常工作,因此显然不是必需的。**

我从github克隆了google测试,并为我的mac构建了它。它工作正常,但是我在示例测试代码中注意到,他们给了他们将测试放在未命名的名称空间中的条件。有人知道为什么吗?

例如,请参见以下文件:googletest / googletest / samples / sample1_unittest.cc(https://github.com/google/googletest/blob/master/googletest/samples/sample1_unittest.cc#L41

该文件的一部分如下所示:

// Step 1. Include necessary header files such that the stuff your
// test logic needs is declared.
//
// Don't forget gtest.h, which declares the testing framework.

#include <limits.h>
#include "sample1.h"
#include "gtest/gtest.h"
namespace {

// Step 2. Use the TEST macro to define your tests.
...
TEST(FactorialTest, Negative) {
// This test is named "Negative", and belongs to the "FactorialTest"
// test case.
EXPECT_EQ(1, Factorial(-5));
EXPECT_EQ(1, Factorial(-1));
EXPECT_GT(Factorial(-10), 0);
}
...
}  // namespace
Run Code Online (Sandbox Code Playgroud)

有谁知道为什么所有测试都在一个未命名的命名空间中?我尝试删除未命名的名称空间,但该示例仍然可以正常工作,因此显然对于此特定示例而言没有必要。

Kev*_*vin 5

我认为Mike Kinghan的评论回答了这个问题,尤其是那部分

你不需要问程序员为什么没有把东西放到全局命名空间中。你需要问他们为什么有。

但是,我认为从教学上讲,举一个例子说明如果不遵循良好的编码实践并因此错误地违反ODR可能发生的恐怖事件,这是一个好主意。

首先,要将下面的程序与问题联系起来,需要知道一些 Google Test 宏创建了新类。现在,考虑以下程序

myClass1.h

#ifndef MYCLASS1_H
#define MYCLASS1_H

int f();    

#endif  /* MYCLASS1_H */
Run Code Online (Sandbox Code Playgroud)

myClass2.h

#ifndef MYCLASS2_H
#define MYCLASS2_H

int g();    

#endif  /* MYCLASS2_H */
Run Code Online (Sandbox Code Playgroud)

myClass1.cpp

#include "myClass1.h"

class MyClass {
public:
    void twice() { val *= 2; }
    char val;
};    

int f() {
    MyClass x;
    x.val = 2;
    x.twice();
    return x.val;
}
Run Code Online (Sandbox Code Playgroud)

myClass2.cpp

#include "myClass2.h"

class MyClass {
public:
    void twice() { val *= 2; }
    double val;
};    

int g() {
    MyClass x;
    x.val = 3;
    x.twice();
    return x.val;
}
Run Code Online (Sandbox Code Playgroud)

主程序

#include <iostream>
#include "myClass1.h"
#include "myClass2.h"

int main() {
    std::cerr << f() << std::endl << g() << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

注意这个类MyClass有两个不同的定义。使用g++ 5.4.0-6ubuntu1~16.04.10,编译运行程序

g++ -O3 myClass1.cpp myClass2.cpp main.cpp -o undefined && ./undefined
Run Code Online (Sandbox Code Playgroud)

打印46,这是预期的行为。但是,编译和运行没有优化,即

g++ -O0 myClass1.cpp myClass2.cpp main.cpp -o undefined && ./undefined
Run Code Online (Sandbox Code Playgroud)

打印43

现在,把这个 bug 放在一个重要的程序中,你可能很容易失去一个下午的调试时间,特别是如果这个 bug 休眠了一段时间。另一方面,预先将类包装在匿名命名空间中根本不需要时间,它可以防止错误。我认为这说明了一些良好编码实践背后的基本原理之一:基本风险管理。