もう一度C ++のデリゲートについて

「C ++の最も単純なデリゲート」という記事を読んだ後、私はまったく何も理解していなかったことをしっかりと理解しました。 たぶんこれは、著者がC#言語のデリゲートの概念に自分の考えをアピールしたからかもしれません。 しかし、私は客観的なCを知っています。そこでは、結託が非常に頻繁に発生し、委任へのアプローチはC ++に移植されてもまったく悪くありません。そして、それを書いている人は委任を必要としているので、彼らはこのアプローチをより好むかもしれません。 一度に注意-オブジェクトCのメソッドとオブジェクトのバインディングは完全にランタイムであるため、プラスでは機能しませんが、大きなStraustrupは小さなギャップを残しました-仮想関数のテーブル、それでフィルタリングします。



最初に、目的Cの委任へのアプローチを明確にする必要があります。



したがって、趣味のルールに従って、インターフェイス(@interfaceはプラスのクラスの特定の類似体です。以下、これをクラスとも呼びます)、およびデリゲートメソッドの宣言を持つプロトコル(@protocol)、デリゲートをインストールする必要があるクラスはこれから継承する必要がありますプロトコル(プロトコルをサポートするためにココシニコフの言語で)、およびデリゲートメソッドと実装されたプロトコルサポートを持つクラスへのポインターを持つためにデリゲートを呼び出すクラス 目的のクラスにプロトコルを入力すると、何をすべきかを決定します-コンパイラは警告を表示しますが、すべてが機能しますが、C ++ではこれは機能しません。上記のすべてを熱心に観察する必要があります)。



次に、コードに移動します。 まず、同様のプロトコル/インターフェースのペアを宣言しますが、C ++があるという事実に合わせて調整します。

// SomeInterfaceAndProtocol.hpp #ifndef demo_interface_protocol #define demo_interface_protocol struct _protocol //   objC,      ,        { void virtual ActionString(char *)=0;// ; int virtual ActionRetNums(double S)=0; int virtual length(char *)=0; }; class _interface //   { private: char *text; double flo; int lo; _protocol *delegate;//     public: _interface(int Z, double f, char *u); _interface(int Z, double f, char *u, _protocol *_); void SetDelegate(_protocol *_); void action(); void viewResults(); ~_interface(); }; #endif
      
      







わかりやすくするために、_interfaceのみの関数名では、それらのアルゴリズムは別のファイルとして宣言されていますが、現時点では、上記のコードについて説明する価値があります。 _protocol構造体はデリゲートメソッドのリストであり、男性はそれから継承し、次に特定のアクションを委任するインターフェイス(_interfaceという名前)、目的Cを知っている人々は、デリゲートクラスへのポインタが特定の型を持っていることにすでに気付いています。 コンパイラは、仮想関数のテーブルを介して接続を確立する必要があり、このため、ポインターはそのようなテーブルを持つオブジェクト型を持っている必要があります。



_interfaceクラスには、次の属性が含まれます。文字列へのポインター、整数、小数-これらのプライベートパラメーターにデリゲートがどのように影響するかを明確に示すのに十分です。 そして今、私たちのインターフェースが何をするのかを示す価値があります:



 #include "SomeInterfaceAndProtocol.hpp" #include "math.h" class realprotocol: public _protocol// ,      { int length(char *text) //     { int i=0; while(text[i])i++; return i; } void ActionString(char *stroka)//        { int len=this->length(stroka); int k=0; char Z; while(k!=(int)(len/2)) { Z=stroka[k]; stroka[k]=stroka[len-1-k]; stroka[len-1-k]=Z; k++; }; } int ActionRetNums(double S)//     { return (int)sqrt(S); } };
      
      







注意してください(!): class realprotocol: public _protocol



クラスが単にクラスrealprotocolとして宣言されている場合は、このように記述する必要があります。そして、すべて同じ方法で記述します。さらに機能しません。より収容力があります(上記を参照)が、ここには欠点(および多く)があります。



そして、デリゲートとデリゲートが相互作用するリストを表示します。



 #include <cstdlib> #include "SomeInterfaceAndProtocol.hpp" #include "realprotocol.hpp" realprotocol delegat; _interface delegator=_interface(44, 66.888, "seidal eht rof maj"); int main(int argc, char *argv[]) { delegator.SetDelegate(&delegat); delegator.action(); delegator.viewResults(); system("PAUSE"); return EXIT_SUCCESS; }
      
      







結果のあるコンソール:



画像



それはコードのすべてです-文字列は前に戻され、整数属性は委任のオブジェクトのルールに従って部分的に変更され、部分的にデリゲートのオブジェクトの裁量で、委任の本質を非常によく示しています



このアプローチが理想的ではないことは明らかですが、C ++は一般的に松葉杖なしで委任の素因を持たないため、委任先のオブジェクトは別のオブジェクトからの継承が必要な場合があり、継承へのプロトコルの追加は常に機能しない場合があります(プロジェクトでの複数の継承の使用の禁止、親への他のクラス)。 どうして頭が必要なの? それは正しいです-継承を行う方法がなければ、解決策を考え出すために-C ++標準ではこれを書くことができます:



 class externalclass:someclass1, someclass2 { private: class internalclass:public _protocol { //-- }; internalclass forDelegate; public: _protocol* GetForDelegate() { return &forDelegate; } };
      
      







外部クラスと内部クラスは非常に緊密にリンクされているため、相互作用によって必要なものがすべて提供されます。



要約:



1)委任されるクラス、仮想関数を持つプロトコルクラス、デリゲートを作成し、ポインタを介して委任されたオブジェクトを操作する必要があります。

2)委任されたクラスは、プロトコルから継承する必要があります。



All Articles