アドバイザープロジェクト - ページ 5

 

George Merts
Стандартный CObject - это "объект списка или сортированного массива". CMyObject - это CObject, имеющий определенный тип, и содержащий некоторое значение, данное при его создании. Этот объект мне понадобился всвязи с повсеместным приведением объектов к базовому абстрактному классу - чтобы понимать по указателю, на какой именно объект "на самом деле" указывает. Тип CMyObject - устанавливается как раз той самой функцией SetMyObjectType(). Эта функция в обязательном порядке вызывается в конструкторах любых наследников от CMyObject, чтобы назначить идентификатор класса, к которому принадлежит создаваемый объект.

コンストラクタはオープンでパラメータ化されて いません。

class CTradeHistoryI: public CMyObject
{
public:
   void CTradeHistoryI() {    SetMyObjectType(MOT_TRADE_HISTORY_I); };
}

これは、継承者が自身の型を設定してもしなくてもよいことを意味します。そのため、子孫の内部でSetMyObjectTypeメソッドを呼び出すのを忘れると、台無しです。

あなたにできることは?

1.作成外からコンストラクタを閉じる必要があります。

class CTradeHistoryI: public CMyObject
{
protected:
   void CTradeHistoryI() {    SetMyObjectType(MOT_TRADE_HISTORY_I); };
}

この場合、CTradeHistoryIの子孫のみがインスタンスを生成できるため、MOT_TRADE_HISTORY_I型が不要になります。MOT_TRADE_HISTORY_I型は、CTradeHistoryIがインターフェースであり、この型のインスタンスは存在し得ないので、現実には存在しないことに注意してください。つまり、コンストラクタを閉じることで、存在しない型の記述という 矛盾を解決しているのです。

2.インスタンス生成の時点で明示的な型付けを要求するように設定しよう。

enum ENUM_OBJ_TYPE
{
   OBJ_HIST_DEALS_LIST,
   OBJ_HIST_ORDERS_LIST
   ...
};

class CTradeHistoryI: public CMyObject
{
private:
   ENUM_OBJ_TYPE   m_obj_type;
protected:
   CTradeHistoryI(ENUM_OBJ_TYPE obj_type)
   {
      m_obj_type = obj_type;
   }
public:
   ENUM_OBJ_TYPE ObjectType(void) const
   {
      return m_obj_type;
   }
};

class CTradeHistory : public CTradeHistoryI
{
public:
   CTradeHistory(void);
};

CTradeHistory::CTradeHistory(void) : CTradeHistory(OBJ_HIST_DEALS_LIST)
{
}

これで、明示的な型指定がない限り、子孫は自分自身を作成することができなくなりました。

 
Vasiliy Sokolov:

誰もが理解できる標準的なCObjectがあるのに、なぜCMyObjectという形で車輪を再発明するのでしょうか?

MQL CObjectでどんないいことがあったのかわかりません。各オブジェクトに不要なポインタを2つ詰め込む=16バイトの損失+メモリ確保と ポインタの初期化で不要なオーバーヘッドが発生。OOP自体がパフォーマンスを低下させるのに、そんな無駄な解決策を加えたら......。
 
Alexey Navoykov:
MQLのCObjectにどんな良さを見出したのか分かりませんが。各オブジェクトに不要なポインタを2つ詰め込む=16バイトの無駄+メモリ確保と ポインタの初期化で不要なオーバーヘッドが発生。OOP自体がパフォーマンスを低下させるのに、そんな無駄な解決策を加えたら......。

まずOOPを学び、それから議論する。m_prev, m_next の初期化は、一般的には行われない。

 
Vasiliy Sokolov:

まずOOPを学び、それから議論する。m_prev, m_nextの初期化は、一般的には何も起こりません。

あなたの後だけです。

というわけで、参考までに、MQLにおけるポインタの初期化は必ず行われます。

 
Vasiliy Sokolov:

コンストラクタはオープンでパラメータ化されて いません。

これは、継承者が自身の型を設定してもしなくてもよいことを意味します。そのため、子孫の内部でSetMyObjectTypeメソッドを呼び出すのを忘れると、台無しです。

何ができるのか?

...

確かに、SetMyObjectType()を指定し忘れると、デフォルトでCMyObject型でオブジェクトが作成されるケースがありますね。

そして、その解決方法は、良いものです。

提案も受け付けます。

でも、protected コンストラクタは好きではありません。

 
George Merts:

確かに、SetMyObjectType()を指定し忘れると、デフォルトでCMyObject型でオブジェクトが作成されるケースがありますね。

そして、その解決方法は、良いものです。

提案を受け付けます。

しかし、私は保護コンストラクタが好きではありません。

保護されたコンストラクタは、そのようなコンストラクタを持つ親から直接継承されたクラスにとってのみ、生活を複雑なものにします。しかし、ユーザーレベルでは、迷うことなく自由に派生物を作ることができるのです。

したがって、その不都合は観察されるべきではない。

また、MQLには型チェックシステムがない、というか、あっても未発達な状態なので、コンストラクタを隠して型を保護するしかないのですが、他の選択肢はありません。

 
Alexey Navoykov:
MQLのCObjectにどんな良さがあるのか分かりませんが。各オブジェクトに不要なポインタを2つ詰め込む=16バイトの損失+メモリ確保と ポインタの初期化で不要なオーバーヘッドが発生。OOP自体がパフォーマンスを低下させるのに、こんな無駄な解決策を加えてしまっては......。

なぜ「役に立たない」のか?私見では、このオーバーヘッドは非常に小さく、リストやソートされた配列を整理するときにCObjectが与えてくれる利便性に見合うものであることは明らかです。

マイクロ秒やバイトを追いかける必要があるのなら、まさにこの「失われたバイト」が多くのリソースを占めないか考えることはもちろん意味があることです。しかし、私が実践しているように、コード作成とメンテナンスの利便性の方がはるかに重要です。

ところで、最近、コードの最適化に携わりました。私のExpert Advisorsは、テスターではなぜか遅すぎたのです。最も遅い機能は、データリフレッシュの時でした。そこで、このリフレッシュを呼ぶことを、あらゆる面で減らすようにしました。しかし、最近になってテスターでコードのプロファイリングができるようになったんです。そして、大変驚いたことに、私のExpert Advisorの時間のほとんどが、(ほとんど)必要のないターミナルの状態を問い合わせる機能に費やされていることがわかりました(リフレッシュのたびに実行され、他の機能と「同時に」行われていただけなのです)。そして何より、空きメモリを要求する関数に無駄がある。端末の状態を起動時に一度だけ問い合わせ、その後、明示的に指摘されたときだけリフレッシュするようにコードを少し変更したところ、テストが3倍以上高速化されました!

つまり、「無駄なオーバーヘッド」は、探しているところではなく、まったく失われている可能性があるのです。

 
George Merts:

だから、「不要なオーバーヘッド」は、探しているところではまったく失われていないかもしれないのです。

反論しないでください。彼の目的はただ一つ、暴言を吐くことだ。彼のような人には、何も証明できないでしょう。このような人物に対処する最良の方法は、完全な無視です。
 
George Merts:

なぜ「役に立たない」のか?私見では、このオーバーヘッドは非常に小さく、CObjectがリストやソートされた配列を整理する際に提供する利便性に見合うものであることは明らかです。

これらの「便利さ」をオーバーに実装しています。どんなリストが、あなたのオブジェクトの何かを変えるのでしょうか?要するに、定数オブジェクトを リストに入れられないことが判明したのです。あるいは、このようなリストの中に自分のオブジェクトがあると想像して、それを関数に送ると、関数もそのリストにそれを入れ、そして、自分のオブジェクトがprevとnextを変更されて戻ってくると、ゲームが始まる......。

文明的な世界では、リストは、必要なポインタを格納する補助的なNodeオブジェクトによって実装されています。また、ユーザーオブジェクトそのものを触ることはナンセンスです。つまり、オーバーヘッドだけでなく、根本的に正しくないということですね。開発者が手早くこしらえただけなのに、まるでそうであるかのように喜んでいる。

 
Alexey Navoykov:

これらの「便利」は、ある場所を通じて実現されます。オブジェクトの何かが変わるようなリストとは、どのようなものなのでしょうか?要するに、定数オブジェクトを リストに入れることはできないのです。あるいは、このようなリストにあるオブジェクトを関数に送ると、その関数もまたオブジェクトをリストに入れ、オブジェクトがprevとnextを変更されて戻ってくると、ゲームが始まるという状況を想像してください ...

文明的な世界では、リストは、必要なポインタを格納する補助的なNodeオブジェクトによって実装されています。また、ユーザーオブジェクトそのものを触ることはナンセンスです。つまり、オーバーヘッドだけでなく、根本的に正しくないということですね。開発者が急遽こしらえただけなのに、さもそうでなければならないかのように喜んでいる。

そうそう、リストに定数オブジェクトを入れることはできないんだ。

しかし、私は常にCObjectの機能を使っており、私の批評家の誰も、Standard Libraryの配列やリストのオブジェクトに似たものを提案することはなかった。

"あるべき姿 "は、誰もが叫ぶ。しかし、何かを提案しても、突然、何もない。

実際に別のソフトウェアソリューションを提供している参加者でも、CObjectの代わりとなるものは提供していない。むしろ、全く使っていない、機能をあまり使っていないことが多く、「1か所への実装」に注意を払っていない、つまり、実装はかなり良いということである。

悪いなら、とっくに代替品を出しているはずだ。