gtest 的未定义引用
Undefined reference with gtest
为什么下面的 ASSERT_EQ
会导致 undefined reference to Bar::kBar
错误?
编译:g++ a.cc -lgtest -lpthread
#include <gtest/gtest.h>
class Bar {
public:
static const size_t kBar = 0;
};
TEST(Basic, Basic) {
ASSERT_EQ(0, Bar::kBar);
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
来自 Googletest 常见问题解答:
编译器抱怨对某些静态常量成员的“未定义引用”
变量,但我确实在 class 正文中定义了它们。
If your class has a static data member:
// foo.h
class Foo {
...
static const int kBar = 100;
};
You also need to define it outside of the class body in foo.cc:
const int Foo::kBar; // No initializer here.
Otherwise your code is invalid C++, and may break in unexpected ways.
In particular, using it in Google Test comparison assertions (EXPECT_EQ, etc)
will generate an "undefined reference" linker error.
这个解释比较玄乎。 (为什么是“无效的C++?”)那是
可能是因为令人满意的解释是相当技术性的。
即使您的 class bar
声明了静态数据成员 kBar
一个初始化程序,不足以为数据成员提供
具有外部 linkage 的定义(即 linker 可以看到),以及
没有任何代码尝试 odr-use1 Bar::kBar
将
遇到未定义的引用 linkage 错误。这可以说明
不涉及 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 开始,您将能够省略超出 class 的定义,如果
你在初始化的 in-class 声明前加上 inline
(这
将使它成为一个定义)。
[1] [ODR-使用](http://en.cppreference.com/w/cpp/language/definition)
>非正式地,如果一个对象的地址被占用,或者一个引用是
>绑定到它,并且如果对它进行函数调用或者它的
>地址已被占用。如果对象或函数是 ODR 使用的,则其定义必须
>存在于程序的某处;违反该规则是 link 次错误。
为什么下面的 ASSERT_EQ
会导致 undefined reference to Bar::kBar
错误?
编译:g++ a.cc -lgtest -lpthread
#include <gtest/gtest.h>
class Bar {
public:
static const size_t kBar = 0;
};
TEST(Basic, Basic) {
ASSERT_EQ(0, Bar::kBar);
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
来自 Googletest 常见问题解答:
编译器抱怨对某些静态常量成员的“未定义引用” 变量,但我确实在 class 正文中定义了它们。
If your class has a static data member:
// foo.h
class Foo {
...
static const int kBar = 100;
};
You also need to define it outside of the class body in foo.cc:
const int Foo::kBar; // No initializer here.
Otherwise your code is invalid C++, and may break in unexpected ways. In particular, using it in Google Test comparison assertions (EXPECT_EQ, etc) will generate an "undefined reference" linker error.
这个解释比较玄乎。 (为什么是“无效的C++?”)那是 可能是因为令人满意的解释是相当技术性的。
即使您的 class bar
声明了静态数据成员 kBar
一个初始化程序,不足以为数据成员提供
具有外部 linkage 的定义(即 linker 可以看到),以及
没有任何代码尝试 odr-use1 Bar::kBar
将
遇到未定义的引用 linkage 错误。这可以说明
不涉及 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 开始,您将能够省略超出 class 的定义,如果
你在初始化的 in-class 声明前加上 inline
(这
将使它成为一个定义)。
[1] [ODR-使用](http://en.cppreference.com/w/cpp/language/definition) >非正式地,如果一个对象的地址被占用,或者一个引用是 >绑定到它,并且如果对它进行函数调用或者它的 >地址已被占用。如果对象或函数是 ODR 使用的,则其定义必须 >存在于程序的某处;违反该规则是 link 次错误。