テンプレート・パラメータ = void* のコンパイラ・バグ - ページ 6

 
Alexey Navoykov:

すべて正常に動作しているのに、なぜこんな作り話を?

ログでは、次のようになります。

void A::~A()
void B::‾B()

なぜ私はそれに引っかかったのか...。

それなら申し訳ない、そんなことができるなんて知らなかったよ、MKLはC++とはずいぶん違うんだ。プラス面では、void*を削除するとUBになります。

 

トレーディング、自動売買システム、トレーディング戦略のテストに関するフォーラム

MetaTrader 5 build 1930の新バージョン:MQL5におけるフローティングチャートウィンドウと.Netライブラリ

アレクセイ・ナヴォイコフ 2018.12.15 02:44

開発者の皆様へ。以前、あるスレッドで、基底クラスから派生クラスへの暗黙のキャストを許すコンパイラの欠陥について議論しましたが、皆さんは気づかなかったようです。 これは深刻な問題で、エラーチェックが難しく、OOPを 積極的に使う場合には常に頭の痛い問題です。 このキャストは明示的にのみ行うべきです。 これはC++とC#両方の一般的なルールです。

class A {  };

class B : public A { };

A* a = new A;

B* b = a;  // Нет ошибки компиляции!

void f(B*) {  }

void OnInit()
{ 
  f(a);  // Нет ошибки компиляции!
}  

そして、ここでどうするか?

class A {  };

class B : public A { };

A* a = new A;

void* v = a;

B* b = v;  // Нет ошибки компиляции!


この動作もエラーとみなすべきでしょうか?

 
Alexey Navoykov:

スタイラーのせいでコードが読みづらくなるのなら、なぜスタイラーを使うのか?

私にとってスタイラーは、そのすべてのルールを柔軟にカスタマイズできてこそ、良いものです。

だから、プリンターで印刷された他人のコードを読んでも(あるいはここのようなフォーラムで読んでも)。

 
fxsaber:
括弧について
((A*)(b.GetPtr())).f(); // Доп. скобки, чтобы подчеркнуть, что именно имелось в виду, не полагаясь на приоритеты.

まあ、あなたには強調されるかもしれませんが、私には混乱するだけです。 しかし、この式を見ると、ここで誰のメソッドが呼ばれているのかすぐに理解できません。 しかし、前の2行では、一度ではっきりします。

括弧が多ければ多いほど、特にスペースで区切られていない場合、何が起こっているのか把握するのに時間を浪費することになる。

 
Alexey Navoykov:

しかし、この式を見る限り、誰のメソッドが呼ばれているのか、すぐには理解できません。 しかし、前の2行では、すべてが一度に明らかになりました。

何が行われているかを正確に理解するには、すべての括弧を開く必要があります。 括弧が多ければ多いほど、何が行われているかを理解するのに時間がかかります。 特に、何らかの方法でスペースで区切られていない場合は、なおさらです。

追加の括弧は読むためのものではありません - 空白を入れるのはスタイラスに任せて ください。

しかし、執筆中の 自制心のために。他の言語にも移植可能なクロスプラットフォームなコード(必ずしもMT4/5だけではない)を書いていることを意識しながら、デリケートな領域で書くときに、なぜ誰かの優先順位に頼らなければならないのか。括弧を追加することで、言語の優先順位による影響を完全に排除している。すべてが明確になるのです。このため、次のビルド以降、この場所で故障することはないという100%の信頼性があるのです。


また、このブラケット地獄を読むときは、ここで言っていることを正確に理解することに時間を割かなければならないだろう。そして、視認性に関しても。

bool a = (1 < 2) && (3 < 4);
bool b = 1 < 2 && 3 < 4;

では、どちらの方がよりビジュアルに優れているのでしょうか?

 
fxsaber:

この行動もミスに含まれるのでしょうか?

もちろん、そうです。これと同じことです。

ということで、本当に問題が起こりうるところでは何も生成されず、少なくとも警告は必要(コンパイルエラーでも いい)であることがわかりました。 しかし、ブラケットを強制されると警告を惜しみません)さらにここでは、ブラケットなしのコンパイルを禁止しようと提案して、叩くと脅している人さえいます)それが我々の生きる道です...。

 
Alexey Navoykov:

もちろんです。これと同じことです。

つまり、本当に問題があって、少なくとも警告が必要な場合(あるいはコンパイルエラー)には何も表示されないということがわかりました。 しかし、括弧があると警告を惜しみません)さらに、ここでは括弧なしのコンパイルを禁止することを提案して、叩くぞと脅す人もいます)それが我々の生き方です......」。

では、あなたにも警告が必要なのですね?どちらの場所でも挙動は曖昧なのに、括弧付きでは警告に反対し、ここでは賛成するというのは、どういうダブルスタンダードなのでしょう?

わかりにくいミスをしないために、警告が必要なのです。つまり、難易度は主観的な評価なのです。だから、ブラケットではミスをしないが、ここではミスができる。そして、私にとってはその逆です。

では、警告を発するルールはどちらに合わせるべきなのでしょうか?

 
Ilya Malev:

StringConcatenateは知りませんでした、MT5ではデザインが変更され、string sがないと使えないのが残念です。また、StringFormatは4でより高速になります。

そして、一般に、文字列を通してポインタを「ポーリング」するこの操作は、何らかの理由で5ではほぼ2倍遅くなりますが、一般に5では速く動作し、時には1桁速くなります

StringConcatenate()が32bitである可能性は、開発者がすでに5と4のメタデータが同じであると書いているため、互換性のために「ラップ」したのかもしれません。

昨日、dynamic_cast< >を使ってあなたの問題を 解決しようとしました。 問題は、MQLがポインタの参照外しを許可していないことです。クラスメソッド内の関数は dynamic_cast<C_myclass >( func( ) ) で呼び出せるので、 dynamic_cast< > でクラスへのポインタを取得できますが、ポインタをどうすればよいのでしょうか。- void *ptr を再代入することはできますが、ポインタを再参照することはできないので、意味がありません。

 
pavlick_:

CArayObjectを廃棄したい場合は、ベースクラスの上にオーバーライド(このhttps://www.mql5.com/ru/forum/170952/page110#comment_9894796 のようなもの)を作り、配列(おそらくあなたのもの)に入れる必要がありますが、そうするとvoid*はもう必要なくなるのです。

void*に反対しているわけではありません。必要なものですが、別の能力で。

参照によるコードの意味がわからない(標準ライブラリも使わないが)。オブジェクトを配列に格納する際に、そのオブジェクトのコピーを作成する必要がある場合、そのクラスで割り当てメソッドやコピーコンストラクタを明示的に宣言して記述しなければなりません。オブジェクトへの参照を配列に入れるだけなら、ラッパーは全く必要ありません(なぜ?)

ちなみに、mqlの「if(p) delete p」は「既存の動的オブジェクトへの参照が指すなら、それを削除する」と同じではないことをご存じないようですね。

class A{};

void OnStart()
 {
  A *a=new A;
  if(a) Print("Кукареку!");
  if(CheckPointer(a)==POINTER_DYNAMIC) Print("Динамический объект существует и может быть удален");
  else                                 Print("Объект не существует, либо он автоматический");
  delete a;
  if(a) Print("Кукареку!");
  if(CheckPointer(a)==POINTER_DYNAMIC) Print("Динамический объект существует и может быть удален");
  else                                 Print("Объект не существует, либо он автоматический");
 }
 
fxsaber:

そして、視認性に関しても。

どちらがわかりやすいですか?

まあ、スタイラーが そうやってフォーマットしてくれたのなら、それはそれでいいんだけど。

1 < 2 && 3 < 4;

となると、やはりスタイリスト次第。私のコードでは絶対にやらない。 私ならこうする。

1<2 && 3<4
либо
1 < 2  &&  3 < 4