這個例子顯示編譯器(msvc14,gcc,clang)的奇怪行爲,但是我沒有找到解釋。不是默認的析構函數導致不完整的類型錯誤
當我們實現pipml習語並使用前向聲明時,我們需要考慮unique_ptr具有自己的具有不完整類型的特定行爲。 這種情況被提及here和here。
但是,當我們將轉發類的定義移動到另一個頭文件並在稍後使用客戶類時在一個地方包含頭文件時,編譯器變得瘋狂 - 在某些特殊的析構函數聲明中,他們說關於不完整類型。
這是一個簡單的例子。如果取消註釋「#define CASE_2」或「#define CASE_3」並嘗試構建它,則會出現編譯錯誤。
文件foo.h中
#ifndef FOO_H
#define FOO_H
class Foo{};
#endif // FOO_H
文件base.h
#ifndef BASE_H
#define BASE_H
#include <memory>
//#define CASE_1
//#define CASE_2
//#define CASE_3
class Foo;
class Base
{
public:
#if defined(CASE_1)
~Base() = default; // OK!
#elif defined(CASE_2)
~Base() {}; // error: invalid application of 'sizeof' to incomplete type 'Foo'
#elif defined(CASE_3)
~Base(); // error: invalid application of 'sizeof' to incomplete type 'Foo'
#endif
// OK!
private:
std::unique_ptr<Foo> m_foo;
};
#endif // BASE_H
文件base.cpp
#include "base.h"
#if defined(CASE_3)
Base::~Base()
{
}
#endif
文件main.cpp中
#include "foo.h" // No matter order of this includes
#include "base.h" //
int main()
{
Base b;
}
不確定,但我認爲編譯器實際上並沒有抱怨析構函數,而是關於默認的構造函數,如果你聲明瞭非默認的析構函數,則缺少 – user463035818
如果你從基地包含foo.h,CASE_3編譯得很好。 CPP,無論如何,你應該這樣做。如果你不包含main.cpp中的foo.h,那麼'CASE_1'不會編譯,你不應該這樣做。 – Slava