簡體   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