2017-07-01 47 views
0

ALL,接口類產品 「使用未定義類型的」

我在foo.h中一個下面的代碼:

class __declspec(dllexport) Foo 
{ 
protected: 
    struct Impl; 
    Impl *pimpl; 
public: 
    std::wstring &GetMember() { return pimpl->m_string; }; 
}; 

struct Foo::Impl 
{ 
    std::wstring m_string; 
}; 

不幸的是這個代碼產生一個錯誤:

Use of undefined type 'Foo::Impl' 

嘗試轉發declare Database :: Impl導致另一個編譯器錯誤。

那麼修復它的最佳方法是什麼?

所有這些都在一個頭文件中。


編輯:

我想我可以把功能在實際實現類,但我真的想消除重複代碼。但是看起來我不會有其他選擇。

+2

如果'Impl'與'Database :: Impl'是相同的類型,那麼這行'pimpl-> m_string'需要看完整的定義而不僅僅是一個前向聲明。如果類型不同,請修改您的帖子爲[mcve]。另外PIMPL習語的要點是在頭文件中沒有實現。 –

回答

2

pimpl->m_string;需要pimpl(即Foo::Impl)的類型爲complete type,但稍後定義;只有前向聲明是不夠的,Foo::Impl需要在之前定義。

我想你正在試圖實現PImpl idiom,這通常用於減少編譯時間依賴性;所以你應該的Foo::ImplFoo::GetMember定義移動到實現文件,像

// Foo.h 
class Foo 
{ 
protected: 
    struct Impl; 
    Impl *pimpl; 
public: 
    std::wstring &GetMember(); 
}; 

// Foo.cpp 
#include "Foo.h" 
struct Foo::Impl 
{ 
    std::wstring m_string; 
}; 

// define Foo::GetMember after the definition of Foo::Impl 
std::wstring &Foo::GetMember() { return pimpl->m_string; } 
+0

我試圖做pimpl爲了解決被導出的std :: wstring的警告。此外,編輯問題以提供更多背景。 – Igor

1

So what is the best way to fix it?

移動的GetMember()定義出一個單獨的翻譯單元(.cpp文件)。

您也應該這樣做,以便申報和執行struct Foo::Impl。這至少是Pimpl Idiom的全部目的。

-1

ALL,

顯然還有一個更簡單的解決方案:移動默認地將Impl結構內部的功能。

謝謝大家的閱讀。

+1

以某種方式擊敗了_Pimpl Idiom_的使用。 –

+0

@ catweazle-1964,有什麼理由? – Igor

+0

_Pimpl Idiom_的要點是將接口的實際實現從其聲明中分離出來(隱藏)。主要原因是:1.實現更改時,您不想重新編譯依賴於頭的所有源。 2.你想在不同的平臺上選擇不同的翻譯單元和你的編譯系統。 –