オブジェクト構築のための C++ の ** イディオム
-
25-09-2019 - |
質問
多くの C++ API (COM ベースの API が思い浮かびます) では、 作る 構築されたオブジェクトへのポインタは通常、 **
ポインター (関数がそれを構築して初期化します)
通常、次のような署名が表示されます。
HRESULT createAnObject( int howbig, Object **objectYouWantMeToInitialize ) ;
-- ただし、新しいオブジェクトが戻り値として渡されることはほとんどありません。
エラーコードを見たいという人以外に、その理由は何でしょうか?を使用した方が良いですか? **
次のような単純な操作では、返されるポインタではなくパターンを使用します。
wchar_t* getUnicode( const char* src ) ;
あるいは、これは次のように書いたほうがよいでしょうか。
void getUnicode( const char* src, wchar_t** dst ) ;
私が考える最も重要なことは、忘れずにそれを解放することです。 **
どういうわけか、割り当てを解除する必要があることを思い出させる傾向があります。
解決
「エラーコードを望むほかに」?
どのようなあなたは、のほかにのがあると思います。エラーコードはかなり唯一の理由です。関数が失敗したことを示すために、いくつかの方法が必要です。それはポインタパラメータ、または戻り値のいずれかを介してそれを行う必要がありますので、Cは、例外を持っていない、と戻り値は、関数を呼び出すときにチェックするために慣用的、かつ容易になります。
(ちなみに、それは必ずしもそうではありません。**
手段は、オブジェクトを解放しなければならないことは普遍的なルールがない、そしてそれはおそらく、任意のクリーンアップするオブジェクトをのことを思い出させることを利用するものに悪い考えです。)
他のヒント
二つの理由が私の心に来ます。
まず、実際のエラーコードです。 C ++以外に、Cは例外を持っていない、とCOMはC-APIです。また、多くのC ++ベースのプロジェクトは、様々な理由のために例外を使用しません。 例えば、戻り値がエラーを通知することができない場合があるかもしれません関数が整数を返した場合、エラーコードを表すことができない整数値で、存在しなくてもよいです。ポインタで、エラーをシグナル伝達が容易な(NULL ==エラー)ですが、いくつかのAPIの設計者は、すべての機能にわたる一貫した方法でエラーを通知することを好むます。
第二には、機能だけで1つの戻り値を持つことができますが、それらを呼び出すと、複数のオブジェクトを作成することができます。あなたは非NULLポインタでこれらの関数を呼び出す場合、一部のWin32 API関数は、必要に応じて充填することができるポインタに複数のポインタを取ります。次の2つのポインタを返すことができない、または戻り値が複数のポインタを含む値でいくつかの構造体である場合は、むしろこれは、使いにくいだろう。ここでは、あまりにも一貫性のあるAPIを達成するための賢明な目標がある。
によって渡される関数引数内の新しいオブジェクト **
優れている。これにより、将来の変更の使用に安心感が得られます void
に bool
たとえば、関数の成功や、関数の動作を提供するその他の情報を返します。
1 行で答えてください: これは、結果として生じるエラーコードにとってはるかに優れています.
エラーコードを見たい人だけでなく、その理由は何ですか?
このため、いくつかの理由があります。そのうちの一つは、(あなたはWinAPIのとWindows COMでこれを参照してください)Cで使用できるインターフェイスを書いてます。
下位互換別の理由(すなわち、インタフェースはそのように書かれた、今それを破壊することは、既存のコードを壊すことになる)である。
このようなコードを使用するときに私は、設計原理のためのCとの互換性で行くと思います。あなたがC言語で記述した場合++あなたが書いたと思います。
retval Myfunction(Result *& output);
の代わりに
retval Myfunction(Result ** output);
または(より良い):
Result *Myfunction();
と関数がエラーに例外をスローしています。
私はわからないんだけど、私はそれはそれを行うための最善の方法です同意...これは良いかもしれない。
Object * createAnObject(int howbig, HRESULT * optPlaceResultCodeHereIfNotNull = NULL);
その方法は、(それに慣れていない人のために少し注意が必要です)をダブル間接約一切メッシングがなく、結果コードを気にしない人は、心配する必要はありませんすべての第二引数について...彼らはただ、戻り値がNULLであるかどうかを確認することができます。
:それはC ++ですので、実際には、あなたは関数オーバーロードを使用して、簡単にはまだ物事を作ることができます
Object * createAnObject(int howbig);
Object * createAnObject(int howbig, HRESULT & returnResultCode);
の COM呼び出し内の任意のメソッド呼び出しは、のHRESULTなければなりません。リターンコードは、フレームワーク上ですべてを活用して、二重のポインタを渡すと、作成したオブジェクトを取得するには、よく知られた方法で取得します。
あなたの質問は、COM / DCOM C ++を使用してプログラミングます。
について私が持っているいくつかの考えを出したとして、あなたの質問が、コメントを応答しません。これらすべての「ポインタ」と「ポインタへのポインタ」、メモリ管理と参照カウントは、私が離れてC ++でのCOMプログラミングをやってから敬遠する理由です。でも代わりにATLで、私はそれが自然十分に見ていないという単純な理由のためにそれを嫌います。それを言って、私は、ATLを使用していくつかのプロジェクトを行いました。
当時の代替は、使用VBです。 VBのコードは、COMやDCOMプログラミングのために、より自然に見えます。
今日、私はC#を使用します。