記事"MQL5でのオブジェクトポインターの使用"についてのディスカッション - ページ 3 12345 新しいコメント Rashid Umarov 2014.01.23 07:42 #21 このような場合、ポインターは使わないこと。 Vasiliy Sokolov 2014.01.23 07:50 #22 Barbarian2:MQL5とMQL4のポインタと参照についてまだ理解していません。参照渡しとポインターの違いは、余分なコードを除いて何なのでしょうか?C++では違いがありますが、ここではどうなのでしょうか?もっと詳しく書くのが難しくなければ。参照渡しでは、参照渡しされたオブジェクトを初期化する必要があります。ポインタ渡しにはこの制約がない:class CShape { public: string name; }; void OnInit() { CShape* shape = NULL; TestShapePointer(shape); //Critical Error! TestShapeRef(shape); } void TestShapeRef(CShape& shape) { printf(shape.name); } void TestShapePointer(CShape* shape) { if(CheckPointer(shape) != POINTER_INVALID) printf(shape.name); } TestShapeRef関数を呼び出すと、シェイプが初期化されていないので、コードはクラッシュする。一方、TestShapePointer関数の内部では、渡されたオブジェクトが初期化されているかどうかを常にチェックする必要があります。従って、非経験的なルールに従ってください:オブジェクトが関数に渡される時点で存在することが保証されている必要がある場合は、"&"パスを使用します。オブジェクトの状態が未定義の場合は、"*"ポインタ渡しを使い、関数内で渡されたポインタの有効性をチェックする。もうひとつ、微妙なニュアンスの違いを覚えておく必要がある。先ほどの例を考えてみよう:class CShape { public: string name; }; void OnInit() { CShape* shape = NULL; TestShapePointer(shape); printf(shape.name); //ERROR (!?) } void TestShapePointer(CShape* shape) { if(CheckPointer(shape) == POINTER_INVALID) shape = new CShape(); printf(shape.name); } このプログラムは正しく動くだろうか?いや、TestShapePointer関数でオブジェクトの生成が保証されているように見えるにもかかわらず、printf(shape.name); //ERROR(!?)という行で "invalid pointer access "というエラーで終わってしまうだろう。ポイントは、実際にはshapeの代わりにNULL参照が渡されたということです。つまり、関数内のshapeと渡されたshapeは別の オブジェクトなのです!したがって、関数を終了した後もshapeはNULLのままであり、関数内のshapeポインタは失われている(スタックでクリアされている)。つまり Anatoli Kazharski 2014.11.05 14:47 #23 異なる型のオブジェクトで配列を作ることは可能ですか?次の例を見てみましょう://+------------------------------------------------------------------+ //|#テストmq5 //| Copyright 2014, MetaQuotes Software Corp. //|http://mql5.commql5.com //+------------------------------------------------------------------+ #property copyright "Copyright 2014, MetaQuotes Software Corp." #property link "http://www.mql5.com" #property version "1.00" //--- #include <ChartObjects\ChartObjectsTxtControls.mqh> //--- CChartObjectRectLabel rect_label; CChartObjectButton button; CChartObjectEdit edit; //--- CChartObject *objects[]; //+------------------------------------------------------------------+ //| スクリプト番組開始機能| //+------------------------------------------------------------------+ void OnStart() { edit.Create(0,"edit_1",0,20,20,100,20); button.Create(0,"button_1",0,20,40,100,20); rect_label.Create(0,"rect_label_1",0,20,60,100,20); //--- AddObjectToArray(edit); AddObjectToArray(button); AddObjectToArray(rect_label); //--- //オブジェクト[0]。// CChartObjectEditクラスのメソッドにアクセスするには? //オブジェクト[1]。// CChartObjectButtonクラスのメソッドにアクセスするには? //オブジェクト[2]。// CChartObjectRectLabelクラスのメソッドにアクセスするには? //--- while(!IsStopped()) Sleep(1000); } //+------------------------------------------------------------------+ //| オブジェクトの数を返す| //+------------------------------------------------------------------+ int ElementsTotal() { return(ArraySize(objects)); } //+------------------------------------------------------------------+ //| 配列にオブジェクトを追加する| //+------------------------------------------------------------------+ void AddObjectToArray(CChartObject &object) { int size=ElementsTotal(); //--- ArrayResize(objects,size+1); objects[size]=GetPointer(object); //--- if(CheckPointer(objects[size])!=POINTER_INVALID) Print(__FUNCSIG__," >>> array["+IntegerToString(size)+"]: ",objects[size].Name(), "; object type: ",ObjectTypeToString(objects[size].Type())); } //+------------------------------------------------------------------+ //| オブジェクト・タイプを文字列に変換する。| //+------------------------------------------------------------------+ string ObjectTypeToString(int type) { string str=""; //--- switch((ENUM_OBJECT)type) { case OBJ_EDIT : return("edit"); break; case OBJ_BUTTON : return("button"); break; case OBJ_RECTANGLE_LABEL : return("rectangle label"); break; } //--- return("undefined object type"); } //+------------------------------------------------------------------+ //---継承されたクラスのメソッドにアクセス するには? Rashid Umarov 2014.11.05 15:03 #24 tol64:継承クラスのメソッドにアクセス するには? 対象の型にキャストしてみましたか? Anatoli Kazharski 2014.11.05 15:06 #25 Rosh: ターゲットタイプをキャストしてみましたか? いいえ、初めて聞きました。どこで読むことができますか? Ilyas 2014.11.05 16:34 #26 tol64: いいえ、初めて聞きました。どこで読むことができますか? よくあるタイプの形容詞 です://+------------------------------------------------------------------+ //|| //+------------------------------------------------------------------+ class CFoo { }; //+------------------------------------------------------------------+ //|| //+------------------------------------------------------------------+ class CBar : public CFoo { public: void func(int x) { Print("Hello from Bar ",x); } }; //+------------------------------------------------------------------+ //|| //+------------------------------------------------------------------+ void func(CFoo *foo) { //--- ポインタから基底型への直接キャストによる呼び出し ((CBar*)foo).func(1); //--- ターゲット型に変換して呼び出し、必要な型を持つポインタのコピーを保存する。 CBar *b=(CBar *)foo; b.func(2); //--- 動的に作成されたクラスを削除する delete foo; } //+------------------------------------------------------------------+ //|| //+------------------------------------------------------------------+ void OnStart() { func(new CBar); } //+------------------------------------------------------------------+ Anatoli Kazharski 2014.11.05 16:44 #27 mql5: 通常のタイプ変換の 例です: ありがとうございます。調べてみます。 TheXpert 2014.11.05 18:26 #28 Rosh: 対象の型にキャストしてみた? くそっ、そのあとで言語安全性について語るのか? Anatoli Kazharski 2014.11.05 18:34 #29 TheXpert: くそっ、そのあとで言語セキュリティの話か? セキュリティホールを見つけたのか?) Denis Kirichenko 2014.11.06 07:28 #30 ポリモーフィズムを 使った方がいいのでは?それは次のようなものだ:CChartObject *ptr_rect_label; CChartObject *ptr_button; CChartObject *ptr_edit; CChartObject *objects[]; //--- ptr_rect_label=new CChartObjectRectLabel; ptr_button=new CChartObjectButton; ptr_edit=new CChartObjectEdit; 12345 新しいコメント 取引の機会を逃しています。 無料取引アプリ 8千を超えるシグナルをコピー 金融ニュースで金融マーケットを探索 新規登録 ログイン スペースを含まないラテン文字 このメールにパスワードが送信されます エラーが発生しました Googleでログイン WebサイトポリシーおよびMQL5.COM利用規約に同意します。 新規登録 MQL5.com WebサイトへのログインにCookieの使用を許可します。 ログインするには、ブラウザで必要な設定を有効にしてください。 ログイン/パスワードをお忘れですか? Googleでログイン
MQL5とMQL4のポインタと参照についてまだ理解していません。参照渡しとポインターの違いは、余分なコードを除いて何なのでしょうか?C++では違いがありますが、ここではどうなのでしょうか?もっと詳しく書くのが難しくなければ。
参照渡しでは、参照渡しされたオブジェクトを初期化する必要があります。ポインタ渡しにはこの制約がない:
TestShapeRef関数を呼び出すと、シェイプが初期化されていないので、コードはクラッシュする。一方、TestShapePointer関数の内部では、渡されたオブジェクトが初期化されているかどうかを常にチェックする必要があります。従って、非経験的なルールに従ってください:
もうひとつ、微妙なニュアンスの違いを覚えておく必要がある。先ほどの例を考えてみよう:
このプログラムは正しく動くだろうか?いや、TestShapePointer関数でオブジェクトの生成が保証されているように見えるにもかかわらず、printf(shape.name); //ERROR(!?)という行で "invalid pointer access "というエラーで終わってしまうだろう。ポイントは、実際にはshapeの代わりにNULL参照が渡されたということです。つまり、関数内のshapeと渡されたshapeは別の オブジェクトなのです!したがって、関数を終了した後もshapeはNULLのままであり、関数内のshapeポインタは失われている(スタックでクリアされている)。つまり異なる型のオブジェクトで配列を作ることは可能ですか?
次の例を見てみましょう:
//---
継承されたクラスのメソッドにアクセス するには?
継承クラスのメソッドにアクセス するには?
ターゲットタイプをキャストしてみましたか?
いいえ、初めて聞きました。どこで読むことができますか?
通常のタイプ変換の 例です:
対象の型にキャストしてみた?
くそっ、そのあとで言語セキュリティの話か?
ポリモーフィズムを 使った方がいいのでは?
それは次のようなものだ: