MQL5'te OOP hakkında sorular - sayfa 45

 
Dmitry Fedoseev :

Ve birisi bu alan başlatmanın ne olduğunu açıklıyor:

bundan daha iyi:

Ve neyse, amaç ne?

const alanları başlatılabilir.

 
Dmitry Fedoseev :

Ve birisi bu alan başlatmanın ne olduğunu açıklıyor:

bundan daha iyi:

Ve neyse, amaç ne?

İlk durumda, bir başlatmanız var ve ikinci durumda, varsayılan başlatılmış alanlar için işlemler zaten gerçekleştirilir. Yani burada her şey, ya bir fark olmaksızın ya da çalışma zamanında boktan bir ekstra eylem bulutu olmaksızın derleyiciye bağlıdır. Artılarda, ikinci seçenek kötü form olarak kabul edilir.
 
= operatörü, beklendiği gibi, r-değerini döndürür (5<(val=7) çalışır), ancak bu sadece transfer semantiği ile, burada değil, ama ne yazık ki istendi, bu yüzden transfer kurucusu yok.
 
Igor Makanu :

tamamen teorik bir soru.

Belki de SB'de böyle bir kurucu çağrısı gördüm:

bu kod arasındaki fark ne olurdu:

Çıktısını aldım, farkı görmedim, o zaman biraz daha spesifik olarak - a1 ve a2 nesnelerinin yapıcılarına zorunlu bir çağrıyı ne verir veya neden kullanabilirim?

ilk seçeneğin "kolaylığı" nedir?

İlk seçenek - Değer başlatma, ikincisi - Varsayılan başlatma olarak adlandırılır. Nesnenin türüne bağlı olarak incelikler ve farklılıklar vardır (varsayılan bir kurucu ile bir toplam olup olmadığı, ...). Örneğin, burada parantezler kullanıldığında ve kullanılmadığında tamamen farklı bir sonuç olacaktır:

#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;
}

Teorinin derinliklerine inmek istiyorsanız, burada https://en.cppreference.com/w/cpp/language/initialization

Not: µl için, bunların hepsi alakalı değildir, ancak referans modelin anlaşılması içindir.

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 :

Teorinin derinliklerine inmek istiyorsanız, burada https://en.cppreference.com/w/cpp/language/initialization

Henüz gerekli değil, ama kaydedeceğim, kaynağı nerede okuyacağımı bileceğim

Herkese teşekkürler!

Vladimir Simakov :
Artılarda, ikinci seçenek kötü form olarak kabul edilir.

karşılaştığım problemin aynısı olacak - sınıfta birden fazla kurucu yazmak gerektiğinde alan başlatma kodunun çoğaltılması

2. seçeneği kullanırsanız, o zaman yinelenen kod ayrı bir yönteme konulabilir ve her kurucuda gerekli eylemler gerçekleştirildikten sonra bu yöntem çağrılabilir (bir yapıya sahip bir sınıf başlatmam var ve 2. seçenek adıdır. bu yapının verilerinin yazıldığı dosya (yedek depolama))


ilginç değil, ama sorun şu ki, sınıfa yeni bir alan eklersem, o zaman bu alanı kurucular olduğu kadar çok kez başlatmayı hatırlamam gerekecek - gerçek şu ki uygun değil mesele değil, ama bunu N kez yapmayı unutabilmen bir problem, IMHO

 
Igor Makanu :

Henüz gerekli değil, ama kaydedeceğim, kaynağı nerede okuyacağımı bileceğim

Herkese teşekkürler!

karşılaştığım problemin aynısı olacak - sınıfta birden fazla kurucu yazmak gerektiğinde alan başlatma kodunun çoğaltılması

2. seçeneği kullanırsanız, o zaman yinelenen kod ayrı bir yönteme konulabilir ve her kurucuda gerekli eylemler gerçekleştirildikten sonra bu yöntem çağrılabilir (bir yapıya sahip bir sınıf başlatmam var ve 2. seçenek adıdır. bu yapının verilerinin yazıldığı dosya (yedek depolama))


ilginç değil, ama sorun şu ki, sınıfa yeni bir alan eklersem , o zaman bu alanı kurucular olduğu kadar çok kez başlatmayı hatırlamam gerekecek - gerçek şu ki uygun değil mesele değil, ama bunu N-kez yapmayı unutabileceğiniz gerçeği, bu bir problem, IMHO

Parametrik olabilen bir makro. Unutmak için (kendim acı çekiyorum), bu da tedavi edilir))))).

 
Igor Makanu :

karşılaştığım problemin aynısı olacak - sınıfta birden fazla kurucu yazmak gerektiğinde alan başlatma kodunun çoğaltılması

2. seçeneği kullanırsanız, o zaman yinelenen kod ayrı bir yönteme konulabilir ve her kurucuda gerekli eylemler gerçekleştirildikten sonra bu yöntem çağrılabilir (bir yapıya sahip bir sınıf başlatmam var ve 2. seçenek adıdır. bu yapının verilerinin yazıldığı dosya (yedek depolama))


ilginç değil, ama sorun şu ki, sınıfa yeni bir alan eklersem, o zaman bu alanı kurucular olduğu kadar çok kez başlatmayı hatırlamam gerekecek - gerçek şu ki uygun değil mesele değil, ama bunu N-kez yapmayı unutabileceğiniz gerçeği, bu bir problem, IMHO

Hadi, her şey çözüldü:

 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
        ...
    }
};

Varsayılan yapıcılara (veya varsayılan başlatmaya) karşı değilim, ancak yapıcınız bir nesneyi (aptal bir toplam değilse) belirsiz bir durumda bırakırsa ve sonra bazı koltuk değnekleriyle önceden başlatırsanız, o zaman her şey yanlış.

Not: Bu arada, profesyonellerde temsilci bir kurucuya sahip olabilirsiniz, elbette bu yeterli değil

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

Hadi, her şey çözüldü:

biraz önümde, sadece bilgisayarın başına oturdu

@Vladimir Simakov'un doğru başlatmayı unutmamak için sınıf alanlarını bir makro kullanarak başlatma tavsiyesi, evet, bu iyi bir numara, ancak kod alanları başlatan bir yöntemi çağırmaya benzer şekilde okunacak olsa da, ne kadar iyi olduğunu hayal etmek zor ...


Örneğiniz de en rafine değil, ancak sorunu tam olarak kendim için yaptığım gibi çözüyor - ayrı bir başlatma yöntemi \

IMHO, burada soru şu amaçlara yöneliktir - gerekli tüm alanların olacağı temel sınıfı doğru bir şekilde yazmak, ondan miras almak, yapıcıyı korumak ve temel sınıfı mirasçılardan başlatmak, böylece "unutmaya" karşı korumak - orada varsayılan kurucu değil mi? ve bir üçüncü taraf çağrısı tarafından başlatılmaya karşı koruma olacak - yapıcı korunuyor mu? - en azından Microsoft, "korumalı kurucu" google'da arama yapıp yapmadığınızı görebilir - bir makale olacak


ve benim görevim biraz farklı, özellikle sınıf alanlarının durumunu bir dosyaya kaydetmek için kalıtımdan ayrıldım, 2 sınıftan 2 alanım var ve ayrıca uygun yöntemleri çağırarak durumlarını aynı dosyaya kaydediyorum. Temel sınıftan miras alındığında tüm bunları kaydetmeye çalıştım, çok kafa karıştırıcı bir şema olduğu ortaya çıktı, miras olmadan yeniden yazdım, şimdi her şey "şeffaf" oldu

 
Igor Makanu :

biraz önümde, sadece bilgisayarın başına oturdu

@Vladimir Simakov'un doğru başlatmayı unutmamak için sınıf alanlarını bir makro kullanarak başlatma tavsiyesi, evet, bu iyi bir numara, ancak kod alanları başlatan bir yöntemi çağırmaya benzer şekilde okunacak olsa da, ne kadar iyi olduğunu hayal etmek zor...


Örneğiniz de en rafine değil, ancak sorunu tam olarak kendim için yaptığım gibi çözüyor - ayrı bir başlatma yöntemi \

IMHO, burada soru şu amaçlara yöneliktir - gerekli tüm alanların olacağı temel sınıfı doğru bir şekilde yazmak, ondan miras almak, yapıcıyı korumak ve temel sınıfı mirasçılardan başlatmak, böylece "unutmaya" karşı korumak - orada varsayılan kurucu değil mi? ve bir üçüncü taraf çağrısı tarafından başlatılmaya karşı koruma olacak - yapıcı korunuyor mu? - en azından Microsoft, "korumalı kurucu" google'da arama yapıp yapmadığınızı görebilir - bir makale olacak


ve benim görevim biraz farklı, özellikle sınıf alanlarının durumunu bir dosyaya kaydetmek için kalıtımdan ayrıldım, 2 sınıftan 2 alanım var ve ayrıca uygun yöntemleri çağırarak durumlarını aynı dosyaya kaydediyorum. Temel sınıftan miras alındığında tüm bunları kaydetmeye çalıştım, çok kafa karıştırıcı bir şema olduğu ortaya çıktı, miras olmadan yeniden yazdım , şimdi her şey "şeffaf" oldu

Burada bu kadar kafa karıştırıcı olan ne?

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

Burada kafa karıştıran ne?

bu tam olarak bıraktığım şey, ama ilk başta yaptım

bu yaklaşımla - "her şeyin olduğu yerde" temel sınıftan miras alın - her şey çalışır, ancak birkaç sınıf alanı oluşturmaya çalışmak ve sonra her sınıf alanına birkaç alan eklemek istediğimize kadar, hadi hepsini yenelim dinamik bir sınıf dizisi

ve Save (int hndl) yönteminin kendisini anlıyoruz - bunu temel sınıfta uygulayamıyoruz, bu yöntem esasen tartışıldığı gibi hiç gerekli olmayan bir arayüz olacak - arayüzler olmadan da yazabilirsiniz

bununla, sorun değil, hepsi bir zevk ve görev meselesi, genellikle kod esnekliği konusundaki çabalarımı en üst düzeye çıkarırım - minimum hareket - sonuç çözülmüş yeni bir problemdir, terminolojiyi affet)))


ve sorun şu ki, bir dosyaya kaydetmeyi uygularken, farklı türlerdeki toplam kayıt sayısını tanımlamanın gerekli olacağı bir dosya başlığı geliştirmek gerekecek, o zaman mantığı kaybetmemek gerekecek / her şeyi doğru okumak için veri kaydetme sırası .... ve bir sınıfta en az bir alan değiştirilirse final olacaktır

IMHO, temel sınıftan bu tür "hafif" mirasın karmaşıklığı - küçük bir veritabanının geliştirilmesi ve bakımına, herhangi bir sınıftaki değişikliklerin sürekli izlenmesine bağlıdır.

Neden: