MQL5におけるOOPに関する質問 - ページ 45

 
Dmitry Fedoseev:

どなたか、このフィールドの初期化がどのように良いのか説明していただけませんか?

はこれよりマシです。

そして、そもそも何が言いたいのか?

const フィールドを初期化することができる。

 
Dmitry Fedoseev:

どなたか、このフィールドの初期化がどのように良いのか説明していただけませんか?

は、これよりも優れています。

そして、そもそも何が言いたいのか?

最初のケースでは初期化が行われ、2番目のケースでは、デフォルトで初期化されたフィールドに対して操作が行われます。つまり、コンパイラ次第で、何も変わらないか、実行時に余計な動作が発生するか、どちらかになるわけです。プラスでは、2つ目のバリエーションは悪い形とみなされます。
 
=演算子は、当然のように、r値を返しますが(5<(val=7)が効きます)、ちょうどキャリーセマンティクスで、ここにはありませんし、悲しいかな、要求されたので、キャリーコンストラクタもないのです。
 
Igor Makanu:

という質問は、純粋に理論的なものです。

は、おそらくSBで、このようなコンストラクタの呼び出しを見たことがあります。

このコードはどう違うのでしょう。

ではもう少し具体的に、a1 と a2 オブジェクトの強制的なコンストラクタ呼び出しを使用できるのはなぜですか?

最初の選択肢の「便利さ」とは何でしょうか?

最初のオプションは - Value initialization、2番目は - Default initializationと呼ばれています。オブジェクトの種類(集合体か、デフォルトコンストラクタか、など)によっても微妙な違いがあります。例えば、ここで括弧を使うのと使わないのでは、結果が全く違ってきます。

#include <iostream>
using namespace std;
struct S {
        int i;
        int q;
        int f;
};
struct Q : S {
        Q():S() {}
        //Q() {}
};
int main() {
        Q s;
        cout << s.i << s.q << s.f << endl;
}

耳までしっかり理論を把握したい方はこちらへhttps://en.cppreference.com/w/cpp/language/initialization

ZS:全てがmclに関係しているわけではなく、リファレンスモデルの理解としてです。

Initialization - cppreference.com
  • en.cppreference.com
Initialization of a variable provides its initial value at the time of construction. The initial value may be provided in the initializer section of a declarator or a new expression. It also takes place during function calls: function parameters and the function return values are also initialized. For each declarator, the initializer may be one...
 
Vict:

理論に耳を傾けたい方はこちらへhttps://en.cppreference.com/w/cpp/language/initialization

まだ必要ないが、ソースを読む場所がわかるように保存しておく。

皆さん、ありがとうございました。

ウラジミール・シマコフ
プラスでは、2番目の選択肢は悪い形式とみなされます。

クラス内に複数のコンストラクタを書く必要がある場合、私が遭遇したのと同じ問題、つまりフィールドの初期化のためのコードの重複が発生します。

variant 2 を使う場合は、重複するコードを別のメソッドに入れ、各コンストラクタで必要な処理を行った後にこのメソッドを呼び出します(私は、クラスの初期化を構造体で、variant 2 をこの構造体のデータを書き込むファイル名で行っています(バックアップ保存))。


あの繰り返しコードが悪いと書くのは...。しかし、クラスに新しいフィールドを追加した場合、コンストラクタの数だけこのフィールドを初期化することを忘れてはなりません。

 
Igor Makanu:

まだ必要ないが、原典を読む場所がわかるので、持っておこうと思う。

皆さん、ありがとうございました。

クラス内に複数のコンストラクタを書く必要がある場合、私が遭遇したのと同じ問題、つまりフィールドの初期化のためのコードの重複が発生します。

variant 2 を使う場合は、重複するコードを別のメソッドに入れ、各コンストラクタで必要な処理を行った後にこのメソッドを呼び出します(私は、クラスの初期化を構造体で、variant 2 をこの構造体のデータを書き込むファイル名で行っています(バックアップ保存))。


あの繰り返しコードが悪いと書くのは...。し かし、クラスに新しいフィールドを追加した場合、コンストラクタの数だけこのフィールドを初期化することを忘れてはなりません。

パラメトリックも可能なマクロ。物忘れ(私自身悩んでいます)もこれで治ります)))

 
Igor Makanu:

クラス内に複数のコンストラクタを記述する必要がある場合、フィールドの初期化コードが重複してしまうという、私が遭遇したのと同じ問題が発生する可能性があります。

バリアント2を使う場合は、重複するコードを別のメソッドに入れ、各コンストラクタで必要な処理を行った後にこのメソッドを呼び出します(私は、クラスの初期化を構造体で、バリアント2をこの構造体のデータを書き込むファイル名で行っています(バックアップ保存))。


あの繰り返しコードが悪いと書くのは...。面白くはないのですが、問題は、クラスに新しいフィールドを追加した場合、コンストラクタの数だけこのフィールドを初期化するのを忘れないようにしなければならないことです - 便利ではないのですが、N回忘れることがあるという事実が問題なのです、イミフ

さあ、すべては解決できる。

class Q {
    void ctr_base(T t, S s) {//make init tasks
        }
public:
    Q(T t, S s, int i) {
        // make base init
        ctr_base(t, s);
        // make additional tasks
        ...
    }
    Q(T t, S s, strint str) {
        // make base init
        ctr_base(t, s);
        // make additional tasks
        ...
    }
};

デフォルトのコンストラクタ(あるいはデフォルトの初期化)に反対するわけではありませんが、もしコンストラクタがオブジェクトを(まあ、馬鹿な集合体でないなら)未定義の状態にしたまま、何らかの手段で初期化するのなら、それはすべて間違っていると思います。

ZS: ところで、プロではコンストラクタをデリゲートすることができます。

class Foo {
public: 
  Foo(char x, int y) {}
  Foo(int y) : Foo('a', y) {} // Foo(int) delegates to Foo(char,int)
};
 
Vict:

さあ、解決可能です。

私の少し前に、ちょうどPCの前に座ったところです。

Vladimir Simakovの アドバイスでは、マクロを使ってクラスのフィールドを初期化し、適切に初期化することを忘れないようにとのことですが、まあ、そうですね、良いトリックです。


あなたの例は最も洗練されたものではありませんが、私が現在行っている方法と全く同じように問題を解決しています - 別の初期化メソッドです。

つまり、必要なフィールドをすべて含む基底クラスを作成し、それを継承して、コンストラクタをprotectedにして、継承先から基底クラスを初期化すれば、「忘却」からの保護になる、というのが正しい方法です。- 少なくとも、Mikrosoftで "protected constructor "でググれば、記事があります。


私の問題は少し違っていて、私は意図的に継承を残し、クラスのフィールドの状態をファイルに保存するために、私は2つのクラスの2つのフィールドを持っていて、それらの状態も適切なメソッドを呼び出すことによって同じファイルに保存されています。ベースクラスを継承したときに全部保存しようとしたら、非常に面倒なことになったので、継承せずに書き直したら、今は全部「透明」になりました。

 
Igor Makanu:

私より少し先に、PCに座ったところ。

Vladimir Simakov氏の アドバイスでは、マクロを使ってクラスのフィールドを初期化することで、初期化を忘れないようにするとのことですが、確かに良い方法ですね。


あなたの例は最も洗練されたものではありませんが、私が現在行っている方法と全く同じように問題を解決しています - 別の初期化メソッドです。

つまり、必要なフィールドをすべて含む基底クラスを作成し、それを継承して、コンストラクタをprotectedにして、継承先から基底クラスを初期化すれば、「忘却」からの保護になる、というのが正しい方法です。- 少なくとも、Mikrosoftで "protected constructor "でググれば、記事があります。


私の問題は少し違っていて、私は意図的に継承を残し、クラスのフィールドの状態をファイルに保存するために、私は2つのクラスの2つのフィールドを持っていて、それらの状態も適切なメソッドを呼び出すことによって同じファイルに保存されています。 基底クラスから継承したときにすべてを保存しようとしたら、非常に複雑になったので、 継承せずに書き直したところ、すべてが「透明」になったのです。

何がそんなにわかりにくいんだ?

...
virtual void CBase::Save(int hndl){...}
...
CObj:public CBase
...
void CObj::Save(int hndl){
   CBase::Save(hndl);
   ...
}
 
Vladimir Simakov:

何がそんなにわかりにくいんだ?

それこそ、私が逃げ出したようなものです。

このアプローチでは、「すべてのものがある」ベースクラスを継承することで、すべてがうまくいきますが、いくつかのクラスフィールドを作ってみて、それぞれのフィールドクラスにいくつかのフィールドを追加して、クラスの動的配列で すべてを釘付けにするまでは

で、Save(int hndl) メソッド自体を基底クラスで実装できないことがわかります。このメソッドは実際にはインターフェースになりますが、これは上で述べたように全く必要ありません。インターフェースなしで書くことができるのです

私は通常、コードの柔軟性、つまり最小限の手間で最大限の努力をしますが、その結果、新しい問題が解決されます。)


問題は、ファイルへの保存を実装する際に、ファイルヘッダに様々な種類のエントリの合計量を記述し、すべてを正しく読み取るために、データ保存の論理/順序を失わないようにする必要があることです....そしてフィナーレは、1つのクラスのフィールドを1つでも変更すると

ベースクラスから「簡単に」継承することは、小さなデータベースの開発と維持、どのクラスの変更も常に監視することになるのです。