2017-02-21 12 views
-1

"api design for C++"の本(70ページ)の例を理解しようとしています。私は、次の例のようfree_f()autotimer.cppで宣言された自由な関数からAutoTimer::Implのメンバーにアクセスすることが可能に厥引き受けるテキストおよび例から「api design for C++」:C++のシンプルアクセス

// autotimer.h 
class AutoTimer 
{ 
public: 
    explicit AutoTimer(const std::string &name); 
    AutoTimer(); 
    // allow access from other classes/functions in autotimer.cpp 
    class Impl; 
private: 
    Impl* mImpl; 
} 

// autotimer.cpp 
class AutoTimer::Impl 
{ 
public: 
    std::string s; 
} 

void free_f(AutoTimer a){ 
    std::cout << a.mImpl->s << std::endl; 
} 

しかし、私はこれを動作させることはできません。悲しいことに、本にはこれ以上の詳細はありません。だからImplのプライベートメンバーにアクセスするためにfree_f()を修正するにはどうすればよいですか?

私はより明確にするために、コメント(および第1例)

// allow access from other classes/functions in autotimer.cpp

は本「のC++のためのAPIデザイン」からまっすぐであり、私はそれが何を意味するのかを知りたいです。

+2

「a」はポインタではありません。 'mImpl'はポインタです。 – juanchopanza

+1

そして 'mImpl'は' AutoTimer'の 'private'メンバなので、自由な関数はそれにアクセスできません。 –

+0

...それが 'friend'関数でない限り。 –

答えて

0

これはテストされていませんが、あなたのオブジェクトは、標準レイアウト型の場合++法的Cのようになります。

void free_f(AutoTimer a){ 
    Impl* tmp = *reinterpret_cast<Impl**>(&a); 
    std::cout << tmp->s << std::endl; 
} 

そして、あなたはPIMPLとで動作するので、あなたがタイプAutoTimerの参照やポインタを渡す必要があります。さもなければ、一時的なオブジェクトは、破壊時にあなたの実装オブジェクトを破壊します。

http://en.cppreference.com/w/cpp/language/data_members#Standard_layout

+0

ありがとう、それは面白そうですね!キャスティングは私には少し恐ろしいように見えますが、私はこの解決策が好きかどうかはまだ分かりません。ライブラリ内でPimplを扱うのが一般的であることを示すサンプル/ポインタがありますか? – user14419

+0

それはWindows上のライブラリ/ DLLを処理する私の方法です。 friend関数や専用の 'get_pimpl'メンバ関数を使って実装にアクセスすることができます。どちらもインタフェースを拡張します。私はそれが好きではなかった。他のオープンソースプロジェクトの例はありません。私はC++コミュニティがテンプレートのスーパーマジックで非常に扱いにくく、共有ライブラリの境界を越える必要はないと思います。また、いくつかの問題(side-by-side問題など)を防ぐために、DLLインターフェイスで 'std :: string'や他のランタイムタイプを使用しません。 – knivil