使用gtest进行未定义的引用

时间:2017-03-13 04:00:05

标签: c++ googletest

为什么以下ASSERT_EQ会导致undefined reference to Bar::kBar错误?

编译:{{1​​}}

g++ a.cc -lgtest -lpthread

1 个答案:

答案 0 :(得分:8)

来自Googletest常见问题解答:

The compiler complains about "undefined references" to some static const member variables, but I did define them in the class body.

  

如果您的班级有静态数据成员:

// 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,它的定义必须   存在于程序的某个地方;违反这一点的是链接时错误。