繁体   English   中英

使用gtest进行未定义的引用

[英]Undefined reference with gtest

为什么下面的ASSERT_EQ导致undefined reference to Bar::kBar错误的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常见问题解答:

编译器抱怨某些静态const成员变量的“未定义引用”,但我确实在类体中定义了它们。

如果您的类具有静态数据成员:

// 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的情况下进行说明:

foob​​ar.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使用

非正式地,如果一个对象的地址被占用,或者一个引用被绑定到它上面,则该对象被使用,并且如果对它进行函数调用或者使用它的地址,则该函数被使用。 如果一个对象或函数使用了odr,它的定义必须存在于程序的某个地方; 违反这一点的是链接时错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM