問題タブ [pimpl-idiom]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 実装を隠すためにプライベート継承を使用するのは良い考えですか?
例えば
これはPimplイディオムに似ているようです。これには、私が本当に気に入っている2つの利点があります。
- SomePrivateMethodはテスト可能です。代わりにSomePrivateMethodがPointでプライベートとして宣言されている場合、テストから呼び出すことはできません。それをパブリックまたはPointで保護されていると宣言した場合、テストはそれを呼び出すことができますが、Pointの通常のユーザーもそうすることができます。
- プライベートデータへのアクセスは、Pimplイディオムで行う方法と比較して、読み取りと書き込みが簡単です。これは、ポインターを経由する必要がないためです。
。
対。
c++ - 構成可能な実装を指すPimplイディオム
Pimplはバイナリ互換性に優れており、インターフェイスは実装を簡単に切り替えることができるのに適していることを読みました。これらの手法の両方を組み合わせて、アプリケーションが構成ファイルを介して基盤となる実装を切り替えることができるようにする必要があります。
これが私の現在のデザインのレイアウトです。
クラスFoo:クライアント向けAPIを提供します。ここではABIの互換性に関心があります
。クラスIFoo:インターフェイスクラス(すべての純粋仮想メソッド、仮想dtor)
クラスVendor1Foo:Vendor1のライブラリを使用してIFoo
を実装しますクラスVendor2Foo:Vendor2のライブラリを使用してIFooを実装します
pimplを使用せず、インターフェイスを厳密に使用すると、クライアントコードは次のようになります。
問題は、私のクライアントコードがVendor1またはVendor2についてまったく知ることができず、Fooは私がこれを行わなければならない多くのクラスの1つにすぎないことです。
私がやろうとしていることの全体的な概念は次のとおりです。
この問題のエレガントな解決策について何かアイデアはありますか?
これに対処する方法を標準化し、DRYの違反を最小限に抑えるために、いくつかのマクロまたはテンプレートクラス/メソッドを考え出すことを望んでいます。
テンプレートクラスは、ハーブサッターがC ++ 11の一般化されたpimplイディオムを採用するようなpimplヘルパーとして機能する可能性があります:herbsutter.com/gotw/_101また、構成に応じて正しい実装をインスタンス化するためのロジックが含まれている必要があります
ここには、pimplイディオム、ブリッジパターン、およびファクトリパターンの要素があります。上記の例では、initImpl()はファクトリメソッドと考えることができます。これらのパターンのすべてを使用する場合と使用しない場合があるソリューションを探しています。
私はすでにc++pimplイディオムを見てきました:テンプレートパラメータに応じた実装と、SOに関するほとんどのpimplイディオムの質問。タイトルは有望に見えましたが、私の特定のユースケースには役立ちませんでした。
C ++ 11を使用できず、Qtを使用しています。 Dポインターは単一の実装にバインドされているため、私の問題を解決しません。
c++ - ライブラリユーザーからライブラリの依存関係を隠す
静的ライブラリを作成していると考えてください。クラスを持たせましょうFoo
ご覧のとおり、このライブラリ(これを呼びましょうmylib
)は別のライブラリに依存しています。それはうまくコンパイルされます。しかし、ユーザーがそのコード(を使用Foo
して含むmylib.h
)をコンパイルし、私のライブラリとリンクすると、コンパイルは失敗します。これは、ユーザーがdependency_header_from_other_static_library.h
コードをコンパイルするためにもヘッダーファイルを持っている必要があるためです。
この依存関係をユーザーから隠したい。これはどのように行うことができますか?頭に浮かぶのはPIMPL
イディオムです。好き:
Foo
ただし、のクラスのインターフェイスを複製する必要がありますFooImpl
。PIMPL
そして、私の場合に使用するのはやり過ぎですか?
ありがとう。
c++ - ポインターを使用して実装を非表示にする(Pimplイディオム)
次のことを達成することは、どういうわけか可能ですか?
x.hpp-このファイルは他の多くのクラスに含まれています
x.cpp-実装
したがって、基本的には、ユーザーにファイルx.hppを含めてもらいたいのですが、conrete_x.hppヘッダーには注意してください。
私はconcrete_x
ポインタでしか使用できず、プライベートデータメンバーとしてのみ表示されるため、コンパイラが準備するスペースの量を知るには、前方宣言で十分です。よく知られている「pimplイディオム」によく似ています。
これを手伝ってくれませんか。
PS。void*
を使ってキャストしたくない。
c++ - C++ クラスへの Objective-C インスタンス
Objective-c クラスを CPP クラスにインスタンス化するにはどうすればよいですか?
たとえば、私の CPP クラス:
どうすればこれを行うことができますか?
私は、Objective-C には .m を、C++ には .cpp を使用していることに注意してください。
どうもありがとう!
c++ - C ++ 11でプライベートネスト型から継承することは合法ですか?
私がやろうとしているのは、ライブラリクラスのPimplとして可変サイズのPODを使用することです。
次に、次のようないくつかの固定サイズの実装を定義します。
GCCバージョン4.6および4.7は、これを-std=c++0x -Wall -pedantic
でコンパイルするのに問題はありませんが、そのようなプライベートネストされた型名を使用することの合法性についてはまだあいまいです。私の[おそらく時代遅れのドラフト]C++ 11標準のコピーをくぐり抜けても、それ以上の手がかりは得られませんでした。
誰かが私にこれを何らかの方法で(合法であるかどうかにかかわらず)証明する何か(できれば標準のセクション)を指摘することができれば、私は永遠に感謝するでしょう。
c++ - Cのような実装のC++と同等のパフォーマンスのバージョン
この状況に遭遇している間、私はC ++を学んでいます。そこでは、Cで次のシンボリックコードの同等に効率的なバージョンをC++で実装したいと考えています。
要件は次のとおりです。
- 実装はライブラリ(静的/動的)で提供され、ヘッダーはインターフェイス以外の詳細を公開しません
- 同様に効率的である必要があります
仮想関数を使用してインターフェース(COMのようなもの)を公開することはできません。これは、ポリモーフィズム(同じインターフェイスを介して公開される複数の実装)を有効にするソリューションですが、そうではありません。それがもたらす価値は必要ないため、関数の呼び出しにかかるコストを支払う必要がある理由がわかりません。 2つの間接ポインタを介して。だから私の次の考えは、単純なイディオムでした:
shared_ptr <>は適格ではないようです。元の実装には存在しなかった、不要なインターロックされたインクリメント/デクリメントに対して支払います。一方、unique_ptr <>を使用すると、Objをコピーできなくなります。つまり、クライアントはObjを値で受け取る独自の関数を呼び出すことができず、Objは単なるポインターのラッパーであるため、基本的にポインターを値で渡すことはできません。彼は元のバージョンでそれを行うことができました。(参照による受け渡しはまだ適格ではありません:彼はまだポインターをポインターに渡しています)
では、これをC++で実装するための同様に効率的な方法は何でしょうか。
編集:私はそれにもう少し考えを与え、私はこの解決策に到達しました:
ここで、クライアントObjに戻ります。クライアントが他の関数を呼び出して、Objの使用法を配布する必要がある場合、彼はそれらを次のように宣言できます。
c++ - Pimpl + QSharedPointer - デストラクタ = 災害
昨日、私は悲惨な目に遭い、24 時間もフラストレーションを感じていました。問題は、ランダムに発生する予期しないクラッシュに要約されました。さらに複雑なことに、デバッグ レポートにも完全にランダムなパターンがありました。さらに複雑なことに、すべてのデバッグ トレースがランダムなQt ソースまたはネイティブ DLL のいずれかにつながっていました。
以下に、素敵なレポートの例をいくつか示します。
ご覧のとおり、これは非常に厄介なものであり、有用な情報はありません。ただ、一つ気になった点がありました。これはコンパイル中の奇妙な警告であり、目で捉えるのも困難です。
実際、私は最後の手段としてのみこの警告に目を向けました。なぜなら、バグを見つけるための必死の追跡において、コードはすでに文字通りログに感染していたからです。
それを注意深く読んだ後、たとえば、std::unique_ptr
またはstd::scoped_ptr
for Pimplを使用する場合、確実にデストラクターを提供する必要があることを思い出しました。そうしないと、コードはコンパイルさえしません。std::shared_ptr
ただし、デストラクタを気にせず、それがなくても問題なく動作することも覚えています。この奇妙な警告に注意を払わなかったもう 1 つの理由がこれでした。簡単に言えば、デストラクタを追加すると、このランダムなクラッシュが停止しました。QSharedPointer
に比べて、Qtにはいくつかの設計上の欠陥があるようstd::shared_ptr
です。Qt 開発者がこの警告をエラーに変換した方がよいと思います。なぜなら、このようなマラソンのデバッグは、時間、労力、および神経に値するものではないからです。
私の質問は次のとおりです。
- 何が問題なの
QSharedPointer
ですか? なぜデストラクタは非常に重要なのですか? - デストラクタがないのにクラッシュしたのはなぜですか? これらのオブジェクト ( Pimpl +を使用している
QSharedPointer
) はスタック上に作成され、他のオブジェクトはそれらの死後にそれらにアクセスできなくなります。しかし、クラッシュは彼らの死後、ランダムな期間に発生しました。 - 誰もそのような問題に遭遇したことがありますか? あなたの経験を共有してください。
- Qt にそのような他の落とし穴がありますか?
願わくば、これらの質問と私の投稿全般が、私が過去 24 時間にわたって経験した地獄を他の人が回避するのに役立つことを願っています。
c++ - pimplイディオムが正しくないテンプレートクラス
ここのMSDNライブラリで説明されているように、私はpimplイディオムを少し実験したいと思いました。今私Foo.hpp
は
T
パラメータがまだ使用されていない場合。実装はに保存されますFoo.cpp
現在、コンパイラには2つのエラーと1つの警告があります。
use of undefined type 'Foo<T>::Impl'; ... vc\include\memory in line 1150
can't delete an incomplete type; ... vc\include\memory in line 1151
deletion of pointer to incomplete type 'Foo<T>::Impl'; no destructor called; ... vc\include\memory in line 1152
ここでの競合とは何ですか?どうすれば解決できますか?
編集。std::make_shared
1つの古いバージョンに基づいて、-copy&pastefailの呼び出しを削除しました。