問題タブ [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++ - c ++ pimplイディオム:テンプレートパラメータに応じた実装
この質問では、テンプレートの引数に応じて異なるpimpl実装を使用する方法を尋ねましたが失敗しました。
たぶん、この例は私がやろうとしていることをよりよく示しています:
構造体Cを特殊化しようとしても失敗します(上記はコンパイルされません)
それで、それは可能ですか?
私はこのような回避策を知っています:
でもできれば避けたい
c++ - C++ pimpl イディオムと静的メソッドおよびフィールド
PIMPL イディオムの存在下で静的フィールド メソッドを使用する方法をよりよく理解したいと思います。次のコードを検討してください。
MyClass.h ファイル:
MyClass.cpp ファイル:
次の 2 つのエラーがあります。
- メンバー関数 static_method を宣言して静的リンケージを持つことはできません
- static_field はこのスコープで宣言されていませんでした
私はニキビのイディオムにあまり慣れていません。
だから私の質問は、PIMPLイディオムを尊重し、それを正常にコンパイルするために、静的メソッドとフィールド宣言をどのように達成するかです?
このコードで何が間違っていますか?
コードを変更するにはどうすればよいですか?
c++ - クラス定義からプライベート非仮想メソッドを省略する方法は?
次のようなものがあるとしましょう:
a.hpp:
a.cpp:
残念ながら、この場合、「get_complicated()」は A のメソッドではないため、a.cpp はコンパイルに失敗します。
したがって、これを試すことができます:
a.hpp:
しかし、something_complicated が定義されていないため、a.hpp はコンパイルに失敗します。
クラスの場合は something_complicited を前方宣言できますが、おそらく typedef であるため、それはできません。
b_ public を作成せず、a.hpp に something_complicited.hpp を含めずにこれを行う唯一の方法は次のとおりです。
a.cpp:
この問題を回避するためにマクロを定義する必要はありませんか? 代替案はありますか?
c++ - shared_ptrまたはunique_ptrを使用する必要があります
pimplイディオムを使用していくつかのオブジェクトを作成してきましたが、を使用するか、を使用するかがわかりませstd::shared_ptr
んstd::unique_ptr
。
私はそれがより効率的であることを理解していますが、これらのオブジェクトはとにかく比較的重いので、オーバーstd::unique_ptr
のコストは比較的小さいので、これは私にとってそれほど問題ではありません。std::shared_ptr
std::unique_ptr
私は現在std::shared_ptr
、柔軟性が高いという理由だけで取り組んでいます。たとえば、を使用するとstd::shared_ptr
、これらのオブジェクトのコピーを呼び出し元に返すことができる一方で、これらのオブジェクトをハッシュマップに格納してすばやくアクセスできます(イテレータまたは参照はすぐに無効になる可能性があるため)。
ただし、変更はすべてのコピーに影響するため、これらのオブジェクトは実際にはコピーされていません。したがって、std::shared_ptr
コピーの使用と許可は、ある種のアンチパターンまたは悪いことであるのではないかと思いました。
これは正しいです?
c++ - pimpl: pimpl でポインタからポインタへのポインタを避ける
この質問では、「pimpl: shared_ptr or unique_ptr」と尋ねました。pimpl イディオムの適切な使用法は、 aunique_ptr
ではなく aを使用することであると確信しましたshared_ptr
。ユーザーにはポインターがまったくないかのように動作する必要がありますが、shared_ptr
コピー時にエイリアシングが導入されることは明らかであり、これは間違いなくポインターのように動作します。
したがって、ユーザーがshared_ptr
私の pimpl オブジェクトに を作成したいとしましょう (実際に複数のエイリアスが必要な場合など)。例えば:
それは私の実装を指すことになりますshared_ptr
。unique_ptr
次のようなものを達成できればいいのですが:
しかし、どうにかしてポインタからポインタへのポインタを取り除き、pimpl の実装の非表示を維持します。
これを達成する方法についてのアイデア (行 (2) と明らかに変更できてうれしいですが、my_pimpl
行 (3) と (4) は同じままにしておきたい)。
c++ - Pimpl フレームワークのコメント/提案のリクエスト
私は基本的に提案を実装しました。私の質問は、それが実行されたか、実行された場合、どこで実行されたかということです。および/または私がやっていることを行うためのより良い方法はありますか? この投稿の長さについて申し訳ありません。コードを提供する以外に、私のアプローチを説明するより良い方法を知りませんでした。
以前に pimpl という質問をしました: pimpl でポインターへのポインターを回避しますか?
interface
ここでもう一度その質問を説明するために、基本的に、インターフェースと実装があるとしましょうimpl
。さらに、pimpl イディオムのように、impl
.
これを c++0x で行う方法はunique_ptr
、interface
を指す で発言することimpl
です。のメソッドの実際の実装は にinterface
は含まれていません。それらはのインターフェイスと実装の両方とともにmain.cpp
、たとえば で個別にコンパイルされます。interface.cpp
impl
このクラスは、ポインターが存在しないかのように設計されているため、ユーザーに対して効果的に透過的です。表記法ではなく、表記法を使用して.
メソッドを呼び出します->
。コピーする場合は、ディープ コピーの回路図を実装します。
しかし、実際にこのピンプルへの共有ポインターが必要な場合はどうなるか考えていました。を実行することもできますがshared_ptr<interface>
、その場合は shared_ptr から unique_ptr を使用することになり、それは少しばかげていると思いました。insideshared_ptr
の代わりに を使用することもできますが、それでも関数呼び出しの表記法を使用し、ポインターのようには見えないため、浅いコピーを行うとユーザーを驚かせる可能性があります。unique_ptr
interface
.
インターフェイスと互換性のあるandのペアのX
対応する実装を接続し、多くの pimpl 定型文を処理する汎用テンプレート クラスがあれば良いと思い始めました。Y
X
Y
以下は、私がそれをやろうとした方法です。
まず、次から始めますmain.cpp
。
基本的にここにx1
、標準のunique_ptr
pimpl 実装があります。x2
は実際には ashared_ptr
であり、 a によって引き起こされる二重ポインタはありませんunique_ptr
。多くの割り当てとコンストラクターは、テスト専用でした。
今interface.hpp
:
interface_macros.hpp
:
interface_macros.hpp
私が開発したフレームワークに必要ないくつかの定型コードが含まれているだけです。インターフェイスはテンプレート引数として取り、それを基本クラスにします。このコンストラクターは、アクションが発生HANDLER
するベースに物事が確実に転送されるようにします。HANDLER
もちろんinterface
、それ自体は意図的にメンバーもコンストラクターも持たず、いくつかのパブリックメンバー関数のみを持ちます。
今interface.cpp
は私たちの他のファイルです。実際には の実装が含まれておりinterface
、その名前にもかかわらず、 のインターフェースと実装も含まれていますimpl
。ファイルの完全なリストはまだ記載しませんが、最初に含まれていると思われるのはinterface_impl.hpp
(紛らわしい名前で申し訳ありません) です。
ここにあるinterface_impl.hpp
:
get_impl()
メソッド呼び出しに注意してください。これはHANDLER
後で提供される予定です。
impl.hpp
のインターフェースと実装の両方が含まれていますimpl
。これらを分離することもできましたが、必要がありませんでした。ここにあるimpl.hpp
:
を見てみましょうunique_pimpl.hpp
。これは に含まれていたことを思い出してくださいmain.cpp
。したがって、メイン プログラムにはこれが定義されています。
unique_pimpl.hpp
:
ここで、テンプレート クラスINTERFACE
(1 つのパラメータ を持ちHANDLER
、ここでは で埋めますunique_pimpl
) とIMPL
クラス (この場合はimpl
) を渡します。このクラスは、 がunique_ptr
実際に存在する場所です。
get_impl()
これで、探していた機能が提供されます。インターフェイスはこの関数を呼び出すことができるため、呼び出しを実装に転送できます。
見てみましょうunique_pimpl_impl.hpp
:
上記の多くは単なる定型コードであり、期待どおりの動作をします。create(...)
のコンストラクターに転送するだけでimpl
、それ以外の場合はユーザーには表示されません。DEFINE_UNIQUE_PIMPL
また、後で適切なテンプレートをインスタンス化するために使用できるマクロ定義もあります。
これで、次の場所に戻ることができますinterface.cpp
。
これにより、適切なすべてのテンプレートがコンパイルされinstantate_my_unique_pimpl_create_functions()
、引数なしの create がコンパイルされ、それ以外の場合は呼び出されることはありません。impl
main から呼び出したい他のコンストラクターがある場合は、ここでそれらを定義できます (例: my_unique_pimpl::create(int(0))
)。
をもう一度見るとmain.cpp
、 がどのようunique_pimpl
に作成されるかがわかります。しかし、他の結合方法を作成することもできますshared_pimpl
。
shared_pimpl.hpp
:
shared_pimpl_impl.hpp
:
create
for実際には、二重のリダイレクトなしでshared_pimpl
real を返すことに注意してください。shared_ptr
の static_cast はget_impl()
めちゃくちゃです。悲しいことに、継承ツリーを2段階上に移動してから実装に1段階下る以外に、より良い方法を知りませんでした。
たとえば、侵入ポインター用の他の「HANDLER」クラスを作成したり、すべてのヘッダーファイルを従来の方法で含める必要がある単純なスタック割り当て結合を作成したりすることを想像できます。そうすれば、ユーザーは pimpl に対応しているが pimpl を必要としないクラスを作成できます。
すべてのファイルを zip からダウンロードできますここ. それらは現在のディレクトリに抽出されます。gcc 4.4.5 と gcc 4.6.0 の両方で問題なく動作しました。
ですから、私が言ったように、どんな提案やコメントもいただければ幸いです。これが行われた場合 (おそらく私よりも優れています)、私に指示していただければ、それは素晴らしいことです。
c++ - pimpl は匿名の名前空間と互換性がありますか?
pimplパターンを使用して、匿名名前空間で実装クラスを定義しようとしています。これは C++ で可能ですか? 私の失敗した試みを以下に説明します。
実装を名前付きの名前空間 (またはグローバルなもの) に移動せずにこれを修正することは可能ですか?
c++ - 名前のない名前空間を使用せずにヘッダーでC++クラスを非表示にする
私はC++ヘッダーを書いています。
外の世界から隠したいのです(このヘッダーの将来のバージョンでは変更されるか、削除される可能性があるため)。
同じヘッダーに、クラスAのオブジェクトをメンバーとして持つクラスBもあります。
クラスAを外界から隠す適切な方法は何ですか?
名前のない名前空間にAの定義を入れると、コンパイラーは警告を発行するので、内部リンケージの問題のために、別のことをする必要があると思います。
c++ - サードパーティのライブラリ構造体を正しくラップする方法は?
私のプロジェクトでは、絶えず変化するサードパーティのライブラリを使用しています。このライブラリのラッパークラス(ブリッジパターン+ Pimplパターン)があります。したがって、ラッパーの実装を除いて、私のソースはどれもそのライブラリを認識していません。このライブラリにはOptions構造体があります。
これらのオプションを設定できるダイアログを作成するために、この構造体をGUIモジュールで使用できるようにしたいと思います。そのためのラッパー構造体を作成する必要がありますか?例えば
または、その構造体ヘッダーをソースに直接含める必要がありますか?
ラッパーの欠点は次のとおりです。コピー-貼り付け、構造体間で変換するための追加コード。直接の欠点は次のとおりです。単純なイディオムを破る。
この問題に対する他の解決策はありますか?
また、サードパーティのライブラリは絶えず変化していることを強調したいので、ライブラリのすべての新しいバージョンをサポートするためにソースを採用する必要があります。
c++ - にきびのより単純な形
このデザインを選ばない理由:
これの代わりに:
ソース ファイルで定義された変数と静的関数を使用して、実装の詳細を非表示にしてコンパイルを高速化できますか? そうでない場合、この設計 (継承以外) の何が問題になっていますか?