OOP, mql5'te şablonlar ve makrolar, incelikler ve kullanım teknikleri - sayfa 2

 
Ilya Malev :

Birçok stat beyan durumu yaşadım. stat'ın yeniden bildirilmesi koşuluyla, genel düzeyde (OnInit'ten önce) başlatılan sınıflardaki alanlar. alanları sınıf tanımından hemen sonra ve örneğinin global bir değişkenini bildirmeden önce, statik bir alanı başlatma ile ilgili hiçbir zaman sorun olmadı (çünkü bu durumda global olarak kabul edilir ve anladığım kadarıyla sınıf örneğinden önce başlatılır). Yani, metotlar ve fonksiyonlar içinde sadece statik değişken tanımlamayı reddetmeniz yeterlidir ve herhangi bir problem yoktur.

Evet, doğru, normal sınıflarda hemen başlatılır. Ancak şablonda - hayır:

 template < typename T>
class A
{
 public : 
   static int a;
};

template < typename T>
int A::a= 10 ;

int f() { return A< int >::a; }

int a= f();

void OnStart ()
{
   Print (a); // Результат: 0
};
 
Alexey Viktorov :

Yöntemler ve işlevler içinde statik değişkenler tanımlamayı tamamen reddedemezsiniz, ancak en azından diğer statik değişkenleri, statik değişkenlerin bulunduğu yöntemler veya işlevlerle başlatamazsınız.

Bu örnekte, önce static int b değişkeni başlatılacaktır, ancak int a (int n) işlevinin içinde yer alan static int f değişkeni henüz başlatılmamış ve sonuç olarak çöp alıyoruz.

Bu arada, evet, bu başka bir hata. Onlar. Statik / global değişkenlerin ayrı başlatılmasına ek olarak, statik değişkenleri de yanlış sırada başlatır. Ve şimdi bu daha da ciddi bir sorun. Burada " Diğer statik değişkenleri, statik değişkenlerin bulunduğu yöntemler veya işlevlerle başlatma" diyorsunuz. Bunu gerçekte nasıl gözlemlemeyi önerirsiniz? Her fonksiyon bağımsızdır, kendi başına var olur. Değişebilen kendi uygulaması vardır. Daha önce diyelim ki içinde statik bir değişken yoktu ve sonra onu eklemeye karar verdiniz. Ve bu, bir yerde bir şeylerin yanlış çalışmaya başlayabileceği anlamına gelir, çünkü orada, fonksiyonda statik bir değişken olmayacağı gerçeğine dayanıyordu. Ve onu nasıl kontrol edeceksin?

 
Ve genel olarak, bu tür kararlar benim için anlaşılmaz, şunu veya bunu terk etmenin gerekli olduğunu söylüyorlar. Neden reddetmek? Ne için? Sorunu çözebilirseniz ve kendinize hiçbir şey inkar etmeyin. Valla herkesin kendi tercihi...
 
Alexey Navoykov :

Bu arada, evet, bu başka bir hata. Onlar. Statik / global değişkenlerin ayrı ayrı başlatılmasına ek olarak, statik değişkenleri de yanlış sırada başlatır. Ve şimdi bu daha da ciddi bir sorun. Burada " Diğer statik değişkenleri, statik değişkenlerin bulunduğu yöntemler veya işlevlerle başlatma" diyorsunuz. Bunu gerçekte nasıl gözlemlemeyi önerirsiniz? Her fonksiyon bağımsızdır, kendi başına var olur. Değişebilen kendi uygulaması vardır. Daha önce diyelim ki içinde statik bir değişken yoktu ve sonra onu eklemeye karar verdiniz. Ve bu, bir yerde bir şeylerin yanlış çalışmaya başlayabileceği anlamına gelir, çünkü orada, fonksiyonda statik bir değişken olmayacağı gerçeğine dayanıyordu. Ve onu nasıl kontrol edeceksin?

Evet, bunda herhangi bir sorun yok. Değişkenlerin işlevlerle başlatılmasından vazgeçmek yeterlidir ve her şey yerine oturacaktır.

 int a( int n)
{
 static int f= 7 ;
 return (f+=n);
}

void OnTick ()
{
 static int b;
 b=a( 9 );
}
Yani bir patlama ile çalışacak. Sorun nedir??? Tek satırda mı?
 
Alexey Viktorov :

Yani bir patlama ile çalışacak. Sorun nedir??? Tek satırda mı?

Yani buradaki mantığın farklı olduğunu anlıyor musunuz? Her aramada buna bir değer atarsanız, neden b static olarak bildirin?
 
Alexey Navoykov :
Yani buradaki mantığın farklı olduğunu anlıyor musunuz? Her aramada buna bir değer atarsanız, neden b static olarak bildirin?

Kabul ediyorum. Aceleyle, küçük bir numara yaptım. Ancak sonuçta b değişkenine bazı koşullar altında bir değer atanabilir ve koşula bağlı olarak 9 yerine değerler fonksiyona aktarılabilir.


Ama sizin örneğinizde, 'a' değişkeni global düzeyde mi başlatılmalı?

 template < typename T>
class A
{
 public : 
   static int a;
};

template < typename T>
int A::a= 10 ;

int f() { return A< int >::a; }

int a= f();

void OnStart ()
{
   Print (a); // Результат: 0
};

Komut dosyasında başka bir seçenek yoktur, ancak EA'da global düzeyde bir değişken bildirebilir ve OnInit() içinde başlatabilirsiniz.

Başlatma sırasını anlamak ve takip etmek yeterlidir. Önce global değişkenler, sonra statik değişkenler, sonra kodda göründükleri gibi yerel değişkenler.

Değişkenlerin işlevler tarafından başlatılmasını önlemek için belgelerin önerisini ihlal eden bu örnektir. Geliştiriciler için böyle bir uyarı yazmak, nerede mümkün olduğunu ve nerede imkansız olduğunu açıklamaktan daha kolaydı.

Örneğinizden statiği kaldırın ve istediğiniz sonucu alın.

 
Alexey Viktorov :

Ama sizin örneğinizde, 'a' değişkeni global düzeyde mi başlatılmalı?

Gerekli değil, ama benim için daha uygun. Bu bir sabitse (ve genel görünürlükte, kod okuryazarsa çoğunlukla sabitler bildirilir), o zaman burada başka seçenek yoktur.

Komut dosyasında başka bir seçenek yoktur, ancak EA'da global düzeyde bir değişken bildirebilir ve OnInit() ile başlatabilirsiniz.

Başlatma sırasını anlamak ve takip etmek yeterlidir . Önce global değişkenler, sonra statik değişkenler, sonra kodda göründükleri gibi yerel değişkenler.

Değişkenlerin işlevler tarafından başlatılmasını önlemek için belgelerin önerisini ihlal eden bu örnektir. Geliştiriciler için böyle bir uyarı yazmak, nerede mümkün olduğunu ve nerede imkansız olduğunu açıklamaktan daha kolaydı.

Örneğinizden statiği kaldırın ve istediğiniz sonucu alın.

Sarı ile vurgulanan her şey için tek bir sorum var: NEDEN? Sorunun nasıl çözüleceğini zaten buldum.
 
Son sayfadaki dosya güncellendi. Küçük bir hata düzeltildi.
 
Alexey Navoykov :

Gerekli değil, ama benim için daha uygun. Sabitse (ve genel görünürlükte, kod okuryazarsa çoğunlukla sabitler bildirilir), o zaman burada başka seçenek yoktur.

Sarı ile vurgulanan her şey için bir sorum var: NEDEN? Sorunun nasıl çözüleceğini zaten buldum.

Onu yaratmanın bir yolunu buldun.

 
Alexey Navoykov :

Evet, doğru, normal sınıflarda hemen başlatılır. Ancak şablonda - hayır:

Bu sınıfın en az 1 örneği oluşturulmadan önce başlatma aşamasında bir sınıfın statik alanını kullanmaya çalışıyorsunuz. Bana göre bu bir sapkınlık... Her şey şu şekilde yolunda gidiyor:

 template < typename T>
class A
{
 public : 
  A(){}
   static int a;
   int f(){ return a;}
};

template < typename T>
int A::a= 10 ;

A< int > _a;


int a= _a.f();

void OnStart ()
{
   Print (a);
};
Kapsülleme ilkesi genellikle bu tür alanların herkese açık değil özel olması gerektiğini önerir.