我的一個隊友經常使用的PIMPL的變化,他確實是這樣的:使用匿名命名空間結構的pimpl習語:這是安全的嗎?
了foo.h:
namespace { struct Impl; }
class Foo
{
public:
Foo();
~Foo();
void Bar(int n);
/* ... */
private:
std::unique_ptr<Impl> _impl;
};
這裏發生的事情是,他的前瞻性聲明的實現類是在匿名命名空間。然後他將在Foo.cpp中定義Impl
類。
所以結構::Impl
的定義將可用於Foo.cpp
的翻譯單元。其他代碼包括Foo.h
將提出警告,因爲他們顯然無法訪問Foo.cpp
中定義的::Impl
。但是,我們並不需要它們 - 這是一個僅用於Foo.cpp
的類;我們不想想要它可見或在其他地方已知。
雖然我們可以肯定有一個情況上.cpp
文件包括多個頭,各自宣稱自己::Impl
結構,這些實際上並不衝突,因爲結構從未各自的轉換單元之外使用。
tl; dr:這看起來很奇怪,引發警告,看起來好像它可能會引起衝突,但似乎實際上工作。
之所以這麼說,我不舒服有一些提出警告,烘乾,深入到我們的代碼(更多的頭文件,這是在,就越難將是冒了出來。)這是也只是一個噸的警告。
我的隊友支持這個,因爲它很簡單,保持簡單的代碼定義,並讓我們在我們所有的代碼中使用短而一致的類名Impl
。
我不是編碼慣例的堅守者;如果這是我們用例的良好實踐,我不介意。但我希望能夠安心,這是安全和可維護的,並且在某些時候不會在我們的臉上炸開。
重點是,我認爲*,沒有':: Impl'。使用':: Impl'嘗試訪問* global *名稱空間中的符號'Impl',但它不在全局名稱空間中。另一個常見的方法是使'Impl'結構成爲類本身的私有成員。 –
如果這發生在多個翻譯單元使用的頭文件中,那麼我認爲這是ODR違規。每個匿名命名空間在每個翻譯單元中都不相同,因此Foo類在所有翻譯單元中都沒有一致的定義。 –
參見http://stackoverflow.com/a/23653494/951890 –