記事"MQL5でのオブジェクトポインターの使用"についてのディスカッション

 

新しい記事 MQL5でのオブジェクトポインターの使用 はパブリッシュされました:

デフォルトで、MQL5ではすべてのオブジェクトがレファレンスによって渡されますが、オブジェクトポインターを使用する可能性があります。しかし、オブジェクトは初期化されないかもしれないので、ポインター 確認が必要です。 この場合、 MQL5はクリティカルエラーでアップロードされずにプログラムが終了します。自動作成されたオブジェクトはこのようなエラーが発生しないのでその意味で安全です。本記事ではオブジェクトレファレンスとオブジェクトポインターの違いを理解し、ポインターを使うセキュアコードの書き方を考察します。


作者: MetaQuotes Software Corp.

 

特にGetCriticalError_Unsafe.mq5というリストでは、(ファイルのように)pstatusではなくstatusという存在しない変数が参照されています。

また、各CShape継承クラスで独自の変数型を定義する意味は何でしょうか?

また、これについての説明も聞きたいです。GetCriticalError_OnDemandの例からGetCriticalError_Unsafeに切り替えたとき、全体の変更は実質的に関数の引数の型をCHello *pobjectからCHello &pobjectに変えただけでした。同時に、関数呼び出しは変更されず、ポインタ(CHello *)が渡されました。この場合、著者の言葉によれば、「再びクリティカル・エラーが 発生する」。重要なのは、オブジェクトが参照渡しされる場合、初期化されていないオブジェクトが 渡される関数を呼び出す段階でクリティカル・エラーが発生するということです」。 しかしこの場合、関数に渡されるのはポインタであって、参照ではない。これはどこから来るのでしょうか?MQL5がポインターを参照に暗黙的に変換する際のルールについて詳しく教えてください。あるいは、ドキュメントでそれが記述されている場所を教えてください。もしコンパイラが厳密な型付けをサポートしていれば、この例は単に必要な型の引数を持つ関数がないためにコンパイルに失敗するでしょう。

 
marketeer писал(а) # :

特にGetCriticalError_Unsafe.mq5のリストでは、(ファイル内のように)pstatusではなくstatusという存在しない変数が参照されています。

ありがとうございます。記事とファイルを修正しました。

 
marketeer писал(а) # :

各CShape後継クラスに独自の型変数を定義する意味は何でしょうか?

原則的には、このメンバはどこにも使用されないので、削除することができる。理論的には、子孫クラスでオブジェクトの型に依存する関数を実装するために使うことができる。
 
marketeer писал(а) # :
また、この問題について、いくつかの説明をお聞きしたいと思います。GetCriticalError_OnDemandの例からGetCriticalError_Unsafeに切り替えたとき、関数引数の型をCHello *pobjectからCHello &pobjectに変更するだけで、実質的にすべての変更が済みました。同時に、関数呼び出しは変更されず、ポインタ(CHello *)が渡されました。この場合、著者の言葉によれば、「再びクリティカル・エラーが発生する」。重要なのは、オブジェクトが参照渡しされる場合、初期化されていないオブジェクトが 渡される関数を呼び出す段階でクリティカル・エラーが発生するということです」。 しかしこの場合、関数に渡されるのはポインタであって、参照ではない。これはどこから来るのでしょうか?MQL5がポインターを参照に暗黙的に変換する際のルールについて詳しく教えてください。または、ドキュメントでそれが記述されている場所を教えてください。もしコンパイラが厳密な型付けをサポートしていれば、必要な型の引数を持つ関数がないため、この例は単にコンパイルに失敗するでしょう。
引数をポインタとして受け付ける関数が 明示的に定義されて いれば、それが使われます。そのような関数がない場合、オブジェクト・ポインタは自動的にオブジェクトへの参照に変換され、オブジェクトを参照で受け入れる関数が使用されます。
 
Rosh писал(а) # :
原則的に、このメンバはどこにも使われないので、削除することができる。理論的には、オブジェクトの型に依存する関数を実装するために子孫で使用することができます。
現在の例のソースによると、特定の型のシェイプのオブジェクトには、CShape::typeに加えて、例えばCLine::typeのような2つの型変数があるという「熊手」があるということですね。理想的には1つであるべきだ。
 
Rosh писал(а) # :
パラメータをポインタとして受け取る関数が 明示的に定義されて いれば、それが使用されます。もしそのような関数がなければ、オブジェクトのポインタは自動的にオブジェクトへの参照にキャストされ、オブジェクトを参照で受け入れる関数が使われます。
参照とポインタに関する暗黙の変換の方向について、どこかで読むことはできますか?特に、参照からポインタへの逆変換も行われるのでしょうか?
 
marketeer писал(а) # :
参照とポインタに対して行われる暗黙の変換の方向について、どこかで読むことはできますか?特に、参照からポインタへの逆変換も行われるのでしょうか?
オブジェクトのポインタを取得するには、GetPointer()を 使用します。
Документация по MQL5: Общие функции / GetPointer
Документация по MQL5: Общие функции / GetPointer
  • www.mql5.com
Общие функции / GetPointer - Документация по MQL5
 
marketeer писал(а) # :
現在の例のソースによると、特定の型のシェイプのオブジェクトには、CShape::typeに加えて、例えばCLine::typeのような2つの型変数があるという「熊手」があるということですが、正しく理解していますか?理想的には1つであるべきです。

はい、その通りです。あなたが書いたように、各子孫に2つの型変数があります。子孫クラスのコードがコピーされたため、このようになりました。基底クラスのメンバを子孫クラスから直接利用できるようにするには、そのメンバをprotected指定子で 定義するか、そのメンバのpublic get-メソッドとpublic set-メソッドを基底クラスで宣言する必要があります。

例えば、このように:

//+------------------------------------------------------------------+
//|demo_inheritance.mq5
//| Copyright 2010, MetaQuotes Software Corp.
//|http://mql5.commql5.com
//+------------------------------------------------------------------+
#property copyright "2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
class CBase
  {
private:
   int               type;
public:
                     CBase(){type=0;}
   int               GetType(){return(type);}
  };
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
class CSon: CBase
  {
private:
   int               type;
public:
                     CSon(){type=2;}
   void              PrintType();
  };
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
void CSon::PrintType()
  {
   Print("CSon.type =",type);
   Print("CBase.type =",CBase::GetType());
  }
//+------------------------------------------------------------------+
//| スクリプト番組開始機能|
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   CSon  son;
   son.PrintType();
   int father_type=son.GetType();
  }
//+------------------------------------------------------------------+
 
引用

「この例は非常に単純なので、エラーを見つけるのは難しくありません。しかし、あなたのmql5-プログラムが何百行、何千行もある場合、このようなエラーを見つけるのはもっと複雑になるかもしれません。特に、プログラムの動作における異常事態の条件が予測不可能な要因に依存するような場合、例えば、特定の市場など です。"

どうやって?)

 
それは、カップルの仕様が何らかの形で異なっている場合だ。