为什么 google 测试样本将测试放在匿名命名空间中?
Why does google test sample put tests in an anonymous namespace?
这不是 Superiority of unnamed namespace over static? 的副本
在将问题标记为重复之前,请仔细阅读问题。我不是问为什么使用未命名的命名空间而不是静态的!
我在问,为什么 google tests 放在未命名的命名空间中?这是 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
有谁知道为什么所有测试都在未命名的命名空间中?
我尝试删除未命名的命名空间,示例仍然运行良好,因此显然对于这个特定示例来说没有必要。
我认为 Mike Kinghan 的评论回答了问题,尤其是
部分
You don't need to ask a programmer why haven't put stuff into the global namespace. You need to ask why they have.
但是,我认为从教学的角度来说,举一个例子说明如果不遵循良好的编码习惯并因此错误地违反 ODR 可能会发生的恐怖事件是个好主意.
首先,为了将下面的程序与问题联系起来,需要知道一些 Google 测试宏会创建新的 classes。现在,考虑以下程序
myClass1.h
#ifndef MYCLASS1_H
#define MYCLASS1_H
int f();
#endif /* MYCLASS1_H */
myClass2.h
#ifndef MYCLASS2_H
#define MYCLASS2_H
int g();
#endif /* MYCLASS2_H */
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;
}
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;
}
main.cpp
#include <iostream>
#include "myClass1.h"
#include "myClass2.h"
int main() {
std::cerr << f() << std::endl << g() << std::endl;
return 0;
}
请注意 class MyClass
有两个不同的定义。使用 g++ 5.4.0-6ubuntu1~16.04.10,编译和 运行 程序
g++ -O3 myClass1.cpp myClass2.cpp main.cpp -o undefined && ./undefined
打印 4 和 6,这是预期的行为。但是,编译 运行 没有优化,即
g++ -O0 myClass1.cpp myClass2.cpp main.cpp -o undefined && ./undefined
打印 4 和 3!
现在,将这个 bug 放入一个重要的程序中,您可能会很容易地浪费一个下午的调试时间,尤其是当 bug 隐藏了一段时间的时候。另一方面,预先将 classes 包装在匿名名称空间中根本不需要时间,并且可以防止错误。我认为这说明了一些良好编码实践背后的基本原理之一:基本风险管理。
这不是 Superiority of unnamed namespace over static? 的副本
在将问题标记为重复之前,请仔细阅读问题。我不是问为什么使用未命名的命名空间而不是静态的!
我在问,为什么 google tests 放在未命名的命名空间中?这是 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
有谁知道为什么所有测试都在未命名的命名空间中? 我尝试删除未命名的命名空间,示例仍然运行良好,因此显然对于这个特定示例来说没有必要。
我认为 Mike Kinghan 的评论回答了问题,尤其是
部分You don't need to ask a programmer why haven't put stuff into the global namespace. You need to ask why they have.
但是,我认为从教学的角度来说,举一个例子说明如果不遵循良好的编码习惯并因此错误地违反 ODR 可能会发生的恐怖事件是个好主意.
首先,为了将下面的程序与问题联系起来,需要知道一些 Google 测试宏会创建新的 classes。现在,考虑以下程序
myClass1.h
#ifndef MYCLASS1_H
#define MYCLASS1_H
int f();
#endif /* MYCLASS1_H */
myClass2.h
#ifndef MYCLASS2_H
#define MYCLASS2_H
int g();
#endif /* MYCLASS2_H */
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;
}
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;
}
main.cpp
#include <iostream>
#include "myClass1.h"
#include "myClass2.h"
int main() {
std::cerr << f() << std::endl << g() << std::endl;
return 0;
}
请注意 class MyClass
有两个不同的定义。使用 g++ 5.4.0-6ubuntu1~16.04.10,编译和 运行 程序
g++ -O3 myClass1.cpp myClass2.cpp main.cpp -o undefined && ./undefined
打印 4 和 6,这是预期的行为。但是,编译 运行 没有优化,即
g++ -O0 myClass1.cpp myClass2.cpp main.cpp -o undefined && ./undefined
打印 4 和 3!
现在,将这个 bug 放入一个重要的程序中,您可能会很容易地浪费一个下午的调试时间,尤其是当 bug 隐藏了一段时间的时候。另一方面,预先将 classes 包装在匿名名称空间中根本不需要时间,并且可以防止错误。我认为这说明了一些良好编码实践背后的基本原理之一:基本风险管理。