为什么以下ASSERT_EQ
会导致undefined reference to Bar::kBar
错误?
编译:{{1}}
g++ a.cc -lgtest -lpthread
答案 0 :(得分:8)
来自Googletest常见问题解答:
如果您的班级有静态数据成员:
// foo.h
class Foo {
...
static const int kBar = 100;
};
您还需要在foo.cc中的类主体之外定义它:
const int Foo::kBar; // No initializer here.
否则您的代码是无效的C ++,并且可能会以意想不到的方式中断。 特别是在Google Test比较断言中使用它(EXPECT_EQ等) 将生成“未定义的引用”链接器错误。
这种解释相当神秘。 (为什么它是“无效的C ++?”)就是这样 可能是因为一个令人满意的解释是技术性的。
即使您的班级bar
声明了静态数据成员kBar
初始化程序,不足以为数据成员提供
具有外部链接的定义(即链接器可以看到的),和
没有任何试图使用 1 Bar::kBar
的代码
遇到未定义的引用链接错误。这可以说明
不涉及Googletest:
<强> foobar.cpp 强>
#include <cstdlib>
class Bar {
public:
static const std::size_t kBar = 0;
};
bool foo(std::size_t const & k)
{
return k == 0;
}
int main()
{
return foo(Bar::kBar);
}
尝试构建:
$ g++ foobar.cpp
/tmp/ccWaEsDu.o: In function `main':
foobar.cpp:(.text+0x1c): undefined reference to `Bar::kBar'
collect2: error: ld returned 1 exit status
解决方案符合常见问题解答:
#include <gtest/gtest.h>
class Bar {
public:
static const size_t kBar = 0;
};
const size_t Bar::kBar;
TEST(Basic, Basic) {
ASSERT_EQ(0, Bar::kBar);
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
从C ++ 17开始,如果有的话,你将能够省略类外定义
使用inline
为其初始化的类内声明加上前缀(其中
将它定义为。)
<小时/> [1] ODR-use
非正式地,如果对象的地址被采用或参考,则该对象被使用 绑定到它,如果函数调用函数或其函数,则函数使用odr 地址被采取。如果一个对象或函数使用了odr,它的定义必须 存在于程序的某个地方;违反这一点的是链接时错误。