MQL5'te OOP hakkında sorular - sayfa 20

 
Koldun Zloy :
Statik değişken , kalıtım olmadan bile tüm örnekler için bir olacaktır.

kontrol edildi, evet! her şey daha kolaydı!

/+------------------------------------------------------------------+
string MyTerminalInfoString()
  {
   Print ( __FUNCTION__ );
   return ( "ru" );
  }
//+------------------------------------------------------------------+
class B
  {
   protected :
   static const string Language;
public :
                     B() { Print ( __FUNCTION__ ,Language); }
  };
//+------------------------------------------------------------------+
static const string B::Language=MyTerminalInfoString();
//+------------------------------------------------------------------+
B *arrB[ 5 ];
//+------------------------------------------------------------------+
int OnInit ()
  {
   for ( int i= 0 ; i< 5 ; i++)
      arrB[i] = new B;
   return ( INIT_SUCCEEDED );
  }

2019.08.29 15:14:09.847 tst__ EURUSD,M15: başlatıldı

2019.08.29 15:14:09.847 tst__ EURUSD,M15: B::Bru

2019.08.29 15:14:09.847 tst__ EURUSD,M15: B::Bru

2019.08.29 15:14:09.847 tst__ EURUSD,M15: B::Bru

2019.08.29 15:14:09.847 tst__ EURUSD,M15: B::Bru

2019.08.29 15:14:09.847 tst__ EURUSD,M15: B::Bru

2019.08.29 15:14:09.847 tst__ EURUSD,M15: MyTerminalInfoString

Dil değişkeninin yalnızca bir kez başlatıldığını görüyorum, yani. bu daha basit bir çözüm

Teşekkür ederim!

 
Roman :

Söyle bana, farklı olan ne?
Bunun gibi bir nesne veya işaretçi oluşturma

klasik yaratılıştan

C++'daki 1. durumda CClass sınıf tanımlayıcısının isteğe bağlı olmasıyla farklılık gösterir.

 

burada alanları bir kez sabit değerlerle başlatması gereken sınıfımı çizdim, her şey amaçlandığı gibi çalışıyor gibi görünüyor:

 class Cdeal : public CObject
  {

private :
   static const double VolumeMAX;
   static const double VolumeMIN;
   static const double VolumeSTEP;
   static const int   VolumeDIGITS;
   static int         GetDigitsInVolumeStep();
   SSettingsForOrder m_set;
public :
                     Cdeal(SSettingsForOrder &set);
  };
//____________________________________________________________________
static int Cdeal::GetDigitsInVolumeStep()
  {
   long i= 10000000 ,k= long (:: SymbolInfoDouble ( _Symbol , SYMBOL_VOLUME_STEP ) / 0.0000001 );
   int result= 0 ;
   while (result< 7 && k%i> 0 )
     {
      i/= 10 ;
      result++;
     }
   return (result);
  }
//____________________________________________________________________
static const double Cdeal::VolumeMAX = :: SymbolInfoDouble ( _Symbol , SYMBOL_VOLUME_MAX );
//____________________________________________________________________
static const double Cdeal::VolumeMIN = :: SymbolInfoDouble ( _Symbol , SYMBOL_VOLUME_MIN );
//____________________________________________________________________
static const double Cdeal::VolumeSTEP = :: SymbolInfoDouble ( _Symbol , SYMBOL_VOLUME_STEP );
//____________________________________________________________________
static const int Cdeal::VolumeDIGITS = Cdeal::GetDigitsInVolumeStep();
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
Cdeal::Cdeal(SSettingsForOrder &set)
  {
   m_set = set;
  }
//+------------------------------------------------------------------+

2 şeyi sevmiyorum:

1. SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP) çağrısını tekrarlıyorum - çünkü başlatma sırası belirtilmemiş, yani. önce VolumeSTEP'in başlatılacağı gerçeği değil, ancak o zaman GetDigitsInVolumeStep() çağrılacak

2. Statik int GetDigitsInVolumeStep() yöntemini kullanmaktan kurtulmak istiyorum - YouTube'da statik yöntemleri saf OOP'de kullanmanın iyi olmadığı yeterince video gördüm, bu yüzden yel değirmenleriyle savaşıyorum

videoya bağlantılar, temelde aynıdır https://youtu.be/lfdAwl3-X_c ve https://youtu.be/zME4SOCHT0I


Sevmediğim bu 2 noktayı farklı nasıl yeniden yazardım?

 
Igor Makanu :

1. SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP) çağrısını tekrarlıyorum - çünkü başlatma sırası belirtilmemiş, yani. önce VolumeSTEP'in başlatılacağı gerçeği değil, ancak o zaman GetDigitsInVolumeStep() çağrılacak

1. yani statiğin başlatma sırasının tanımsız olduğundan mı korkuyorsunuz? Genel olarak, bu böyle değildir, artılarda, başlatma koddaki tanım sırasına göredir. Endişelenmeyin, önce VolumeSTEP ve ardından VolumeDIGITS.

 
Vict :

1. yani statiğin başlatma sırasının tanımsız olduğundan mı korkuyorsunuz? Genel olarak, bu böyle değildir, artılarda, başlatma koddaki tanım sırasına göredir. Endişelenmeyin, önce VolumeSTEP ve ardından VolumeDIGITS.

evet, korkmuyorum, diyelim ki kendimi koruyorum, kodun en azından derleme davranışını değiştirmeye karşı bir garantisi olması gerektiğini düşünüyorum - genel olarak, EVET

Not: burada, genel olarak, konu neden günde bir kereden fazla ödeniyor - Videodaki gibi bir şey yapmanın ne kadar gerçekçi olduğunu görmek istiyorum, diyor yazar Yegor , etkili bir şey çıkacağından şüpheliyim - şimdi Zaten statik yöntemler kullanıyorum ve şimdiden bazı başlatma şüpheleri ortaya çıktı

 
Vict :

1. yani statiğin başlatma sırasının tanımsız olduğundan mı korkuyorsunuz? Genel olarak, bu böyle değildir, artılarda, başlatma koddaki tanım sırasına göredir. Endişelenmeyin, önce VolumeSTEP ve ardından VolumeDIGITS.

MQL'de de

https://www.mql5.com/ru/docs/basis/oop/staticmembers

Документация по MQL5: Основы языка / Объектно-ориентированное программирование / Статические члены класса
Документация по MQL5: Основы языка / Объектно-ориентированное программирование / Статические члены класса
  • www.mql5.com
Члены класса могут быть объявлены с использованием модификатора класса памяти static. Такие члены данных разделяются всеми экземплярами данного класса и хранятся в одном месте. Нестатические члены данных создаются для каждой переменной-объекта класса. Отсутствие возможности объявлять статически члены класса привело бы к необходимости объявлять...
 
Igor Makanu :

evet, korkmuyorum, diyelim ki kendimi koruyorum, kodun en azından derleme davranışını değiştirmeye karşı bir garantisi olması gerektiğini düşünüyorum - genel olarak, EVET

Not: Burada, genel olarak, neden bir günlüğüne ödediğim konu - Videodaki gibi bir şey yapmanın ne kadar gerçekçi olduğunu görmek istiyorum, diyor yazar Egor , etkili bir şey çıkacağından şüpheliyim - şimdi Zaten statik yöntemler kullanıyorum ve şimdiden bazı başlatma şüpheleri ortaya çıktı

 #ifndef _C_TRADE_CONST_
#define _C_TRADE_CONST_

#define TRADE_CONST_DECL  CTradeConst* cTradeConst
#define TRADE_CONST  cTradeConst
#define _symbol      cTradeConst.symbol
#define _lotDigits   cTradeConst.lotDigits
#define _lotStep     cTradeConst.lotStep
#define _lotMax      cTradeConst.lotMax
#define _lotMin      cTradeConst.lotMin
#define _tickSize    cTradeConst.tickSize
#define _point       cTradeConst.point
#define _stopLevel   cTradeConst.stopLevel
#define _freezeLevel cTradeConst.freezeLevel
#define _digits      cTradeConst.digits
#ifdef __MQL5__
   #define _marginMode        cTradeConst.marginMode
   #define _executionMode     cTradeConst.executionMode
   #define _expirationMode    cTradeConst.expirationMode
   #define _fillingMode       cTradeConst.fillingMode
   #define _orderMode         cTradeConst.orderMode
#endif 

class CTradeConst
  {
public :
   string                   symbol;
   int                      lotDigits;
   double                   lotStep;
   double                   lotMax;
   double                   lotMin;
   double                   tickSize;
   double                   point;
   double                   stopLevel;
   double                   freezeLevel;
   int                      digits;
#ifdef __MQL5__
   ENUM_ACCOUNT_MARGIN_MODE       marginMode;
   ENUM_SYMBOL_TRADE_EXECUTION    executionMode;
   int                            expirationMode;
   int                            fillingMode;
   int                            orderMode;
#endif   
public :
                     CTradeConst( string mSymbol):symbol(mSymbol== NULL ? _Symbol :mSymbol){ if (!Init()) delete GetPointer ( this );}
private :
   bool               Init();
  };
bool CTradeConst::Init( void ){
   if (! MQLInfoInteger ( MQL_TESTER )&&! SymbolSelect (symbol, true )) return false ;
   lotStep= SymbolInfoDouble (symbol, SYMBOL_VOLUME_STEP );
   lotDigits= MathMax (-( int ) MathFloor ( MathLog10 (lotStep)), 0 );
   lotMax= SymbolInfoDouble (symbol, SYMBOL_VOLUME_MAX );
   lotMin= SymbolInfoDouble (symbol, SYMBOL_VOLUME_MIN );
   point= SymbolInfoDouble (symbol, SYMBOL_POINT );
   tickSize= SymbolInfoDouble (symbol, SYMBOL_TRADE_TICK_SIZE );
   stopLevel= SymbolInfoInteger (symbol, SYMBOL_TRADE_STOPS_LEVEL )*point;
   freezeLevel= SymbolInfoInteger (symbol, SYMBOL_TRADE_FREEZE_LEVEL )*point;
   digits=( int ) SymbolInfoInteger (symbol, SYMBOL_DIGITS );
#ifdef __MQL5__
   marginMode=( ENUM_ACCOUNT_MARGIN_MODE ) AccountInfoInteger ( ACCOUNT_MARGIN_MODE );
   executionMode=( ENUM_SYMBOL_TRADE_EXECUTION ) SymbolInfoInteger (symbol, SYMBOL_TRADE_EXEMODE );
   fillingMode=( int ) SymbolInfoInteger (symbol, SYMBOL_FILLING_MODE );
   expirationMode=( int ) SymbolInfoInteger (symbol, SYMBOL_EXPIRATION_MODE );
   orderMode=( int ) SymbolInfoInteger (symbol, SYMBOL_ORDER_MODE );
#endif 
   return true ;}
   
#endif 

Bunun gibi bir şey kullanın:

 #include "CTradeConst.mqh"

#define FLAG_CONST_CREATE_HERE   0x1

class CExample{
   TRADE_CONST_DECL;
   int cFlag;
                  CExample(string mSymbol,CTradeConst* mTradeConst):
                     TRADE_CONST(!CheckPointer(mTradeConst)?new CTradeCons(mSymbol)t:mTradeConst)
                     { if (! CheckPointer (mTradeConst)) cFlag|=FLAG_CONST_CREATE_HERE;}
                 ~CExample()  { if ( bool (cFlag&FLAG_CONST_CREATE_HERE)) delete TRADE_CONST;}
};

Ve bunun gibi kodda:

CTradeConst* tradeConst= new CTradeConst;
CExampe* exsample[ 10 ];
for ( int i= 0 ;i< 10 ;example[i++]= new CExample( _Symbol ,tradeConst));
 
Statik alana sahip seçeneğin büyük bir dezavantajı vardır. Bu sınıfın farklı örneklerinde bu alan için farklı değerlere sahip olamayacaksınız.
 
Vladimir Simakov :

Bunun gibi bir şey kullanın:

Ve bunun gibi kodda:

ATP, biraz yanlış hedef belirledim, böylece yapabilirim

İşte elde etmek istediğim şey:

1. CDeal sınıfı bağımsızdır, sırasını tek bir stratejiye göre açar/kapatır/eşlik eder - stratejiler, optimize edicideki stratejiler karışımında gezinmek için bir numaralandırmadır

2. madde 1'e dayanarak, SYMBOL_VOLUME_MAX, SYMBOL_VOLUME_MIN, SYMBOL_VOLUME_STEP terminal ortam değişkenlerine ve SYMBOL_VOLUME_STEP içindeki karakter sayısına sahip olmak için başka hiçbir yere ihtiyacım olmadığı ortaya çıktı - bu, MQL programının çalışması sırasında değişmez

3. Paragraf 1 ve 2'ye dayanarak - Bir siparişi açma/kapatma/takip etme yöntemlerini ve sipariş özelliklerini tek bir CDeal sınıfında özetleyebilirim - Tüm bunları gelecekte hiçbir yerde kullanmayacağım, değil mi? ? - böylece her şeyi tek bir sınıfa sığdırabilirim


pp 1-3 her şey çözüldü, AMA .. Tamam, statik konusunda yardımcı oldular, bu yüzden bir sertifika olduğu için, en azından kararınızı haklı çıkarabileceğiniz bir şeyle, şimdi kod şöyle:

 class Cdeal : public CObject
  {
private :
   static const double VolumeMAX;
   static const double VolumeMIN;
   static const double VolumeSTEP;
   static const int   VolumeDIGITS;
   static int         GetDigitsInVolumeStep();
   SSettingsForOrder m_set;
public :
                     Cdeal() { Print ( __FUNCTION__ , "VolumeMAX = " ,VolumeMAX, " , VolumeMIN = " ,VolumeMIN, " , VolumeSTEP = " ,VolumeSTEP, " , VolumeDIGITS = " ,VolumeDIGITS); }
  };
//____________________________________________________________________
static int Cdeal::GetDigitsInVolumeStep()
  {
   long i= 10000000 ,k= long (VolumeSTEP/ 0.0000001 );
   int result= 0 ;
   while (result< 7 && k%i> 0 )
     {
      i/= 10 ;
      result++;
     }
   Print ( __FUNCTION__ );
   return (result);
  }
//____________________________________________________________________
static const double Cdeal::VolumeMAX = :: SymbolInfoDouble ( _Symbol , SYMBOL_VOLUME_MAX );
//____________________________________________________________________
static const double Cdeal::VolumeMIN = :: SymbolInfoDouble ( _Symbol , SYMBOL_VOLUME_MIN );
//____________________________________________________________________
static const double Cdeal::VolumeSTEP = :: SymbolInfoDouble ( _Symbol , SYMBOL_VOLUME_STEP );
//____________________________________________________________________
static const int Cdeal::VolumeDIGITS = Cdeal::GetDigitsInVolumeStep();
//+------------------------------------------------------------------+

günlükte alınan 3 Cdeal örneği oluşturuldu:

2019.08.29 21:53:53.613 AnyGrid_v1.00 EURUSD,M30: başlatıldı

2019.08.29 21:53:53.613 AnyGrid_v1.00 EURUSD,M30: Cdeal::CdealVolumeMAX = 100000.0 , VolumeMIN = 0.01 , VolumeSTEP = 0.01 , VolumeDIGITS = 2

2019.08.29 21:53:53.613 AnyGrid_v1.00 EURUSD,M30: Cdeal::CdealVolumeMAX = 100000.0 , VolumeMIN = 0.01 , VolumeSTEP = 0.01 , VolumeDIGITS = 2

2019.08.29 21:53:53.613 AnyGrid_v1.00 EURUSD,M30: Cdeal::CdealVolumeMAX = 100000.0 , VolumeMIN = 0.01 , VolumeSTEP = 0.01 , VolumeDIGITS = 2

2019.08.29 21:53:53.613 AnyGrid_v1.00 EURUSD,M30: Cdeal::GetDigitsInVolumeStep

şimdiye kadar her şey amaçlandığı gibi çalışıyor!


onlar. şimdi tekrar eden kod bölümleri yok (çağrılar) - bu etkili bir koddur, ANCAK statik işlevi kullanmaktan nasıl kurtulur static int Cdeal::GetDigitsInVolumeStep() - videonun planına göre, yazar bunun olduğuna inanıyor OOP kodunu statik işlevler olmadan yazmak mümkün, hala ne olduğunu görüyorum, sadece uygunsuz değil, aynı zamanda Get ve Set yöntemleri hakkında tüm bunları kullanmak her zaman mümkün değil - büyük olasılıkla onlarsız yapacağım, o zaman biz 'görüşürüz


Vladimir Simakov :
Statik alana sahip seçeneğin büyük bir dezavantajı vardır. Bu sınıfın farklı örneklerinde bu alan için farklı değerlere sahip olamayacaksınız.

evet, ATP, bunu biliyorum, görev sadece gereksiz değişkenler ve gereksiz bellek kullanımı olmadan verimli bir kod elde etmektir.



soru çözülmeden kalana kadar: statik işlevi kullanmaktan nasıl kurtulur static int Cdeal::GetDigitsInVolumeStep()

 
Igor Makanu :

burada alanları bir kez sabit değerlerle başlatması gereken sınıfımı çizdim, her şey amaçlandığı gibi çalışıyor gibi görünüyor:

Bu sadece bir test dersi mi yoksa gerçekten kullanacak mısın?
İkincisi ise, o zaman yapmamalısınız. Statik değişkenler , hatırladığım kadarıyla karakter değişikliğinde yeniden başlatılmıyor.
Ve genel olarak, sabit statiği bazı harici değerlerle başlatmak iyi bir fikir değildir; bu, başlatma sırasında mevcut olacakları gerçeği değildir.