Mql5 dilinin özellikleri, incelikleri ve çalışma yöntemleri - sayfa 234

 
fxsaber #:

Süreyi ölçersiniz ve sonucu alırsınız. Bunu TRADE_ACTION_MODIFY üzerinde yaşadım.

nereden, nereye, ne ve hangi koşullar altında ölçüldü?

sadece OrderSendAsync MODIFY ve hemen sonraki işleme 5 saniye ???

çok garip, korkutucu, olasılıksız bir sonuç - testleri iki kez kontrol etmemiz gerekiyor

 
Maxim Kuznetsov #:

Nereden, nereye, ne ve hangi koşullar altında ölçüldü?

sadece OrderSendAsync MODIFY ve hemen sonraki işlem için 5 sn ????

çok tuhaf, korkutucu, olanaksız bir sonuç - testleri iki kez kontrol etmemiz gerekiyor

Fonksiyondan önceki ve sonraki zamanı ölçtüm, farkı hesapladım ve 5 saniye buldum. Savaş danışmanlarında her şey ölçülür, böylece anormal bir durumu çözmek için daha fazla bilgi olur. Bunu gördüm.

 
Boş bir yapı, torunlara uygun atama operatörünü verir.
struct BASE {};

template <typename T>
struct A : public BASE
{
  T Tmp;
};

void OnStart()
{  
  A<double> d;
  A<int> a = d;
}
 

İçinde farklı eylem kuralları verilebilen, ancak kendi aralarında özdeş olarak manipüle edilebilen yapılar oluşturmak gerekiyordu.

Kullanılan teknik bu örnek üzerinde resmileştirildi.

struct NUMBERS
{
  int Num1;
  int Num2;
};

template <typename T>
struct A : public NUMBERS
{
  int Get1() { return(T::Action1(this.Num1, this.Num2)); }
  int Get2() { return(T::Action2(this.Num1, this.Num2)); }
};

class ADDITION
{
public:
  static int Action1( const int Num1, const int Num2 ) { return(Num1 + Num2); }
  static int Action2( const int Num1, const int Num2 ) { return(Num1 - Num2); }
};

class MULTIPLICATION
{
public:  
  static int Action1( const int Num1, const int Num2 ) { return(Num1 * Num2); }  
  static int Action2( const int Num1, const int Num2 ) { return(Num1 / Num2); }  
};

void OnStart()
{
  NUMBERS a = {5, 2};  
  
  A<ADDITION> b = a;
  Print(b.Get1()); // 7
  Print(b.Get2()); // 3
  
  A<MULTIPLICATION> c = b;
  Print(c.Get1()); // 10
  Print(c.Get2()); // 2
}


Ne yazık ki, OOP dillerinin statik metotlar için neden arayüzleri olmadığını anlayamadım.

interface A
{
public:
  static void Func() {} // 'Func' - cannot be declared static
};
 
fxsaber statik yöntemler için arayüzlere sahip olmadığını anlamadım.

Böyle bir korku yaratmalıyım.

#define  INTERFACE \
  static void Func();
  
class A
{
public:
  INTERFACE
  
  static void f() { Print(typename(A)); }
};

class B
{
public:
  INTERFACE
  
  static void g() { Print(typename(B)); }  
};

static void A::Func() {}
static void B::Func() {}

template <typename T>
void Tmp() { T::Func(); }

void OnStart()
{
  Tmp<A>();
  Tmp<B>();
}
 
fxsaber statik yöntemler için arayüzlere sahip olmadığını anlamadım.

Bunu nasıl hayal ediyorsunuz?

Herhangi bir fonksiyonun .text segmentinde adresi vardır.

Herhangi bir üye fonksiyon (metot), bu işaretçiyi ilk parametresi olarak zımnen kabul eder.

Statik metotlar bu işaretçiyi kabul etmezler ve esasen sözdizimsel "şeker" olup, fiilen sıradan fonksiyonlardır.

Bir sanal fonksiyon çağrıldığında, çalıştırılabilir fonksiyonun adresi, işaretçisi sanal fonksiyonun bildirildiği sınıfta örtük olarak bulunan sanal fonksiyon tablosundan alınır. Çalıştırılabilir fonksiyonun işaretçisinin başlatılması, nesnenin bir örneği oluşturulurken gerçekleşir, mantık şöyledir (tüm acemiler için açık olması için bilerek mql ile yazıyorum:

class Base;
class A;
class B;

void FooClassA(Base* p);
void FooClassC(Base* p);

typedef void(*_Foo)(Base*);

class Base{
public:
   Base(): foo(NULL){}
   void Foo() {foo(&this);}
protected:
   _Foo foo;
};

class A: public Base{
public:
   A():a(100){foo = FooClassA;}
   int a;
};

class B: public A{
public:
   B():b(-100){}
   int b;
};

class C: public B{
public:
   C(){foo = FooClassC;}
   int Get() {return a+b;}
};

void FooClassA(Base* p){PrintFormat("%s: %i",__FUNCTION__,dynamic_cast<A*>(p).a);}
void FooClassC(Base* p){PrintFormat("%s: %i",__FUNCTION__,dynamic_cast<C*>(p).Get());}

void OnStart(){
   A a;
   B b;
   C c;
   Base* p = &a;
   p.Foo();
   p=&b;
   p.Foo();
   p=&c;
   p.Foo();
}

Doğal olarak, gerçekte her şey bu şekilde değildir, ancak işleve işaretçinin başlatılması mekanizması tam olarak bu şekildedir. Buna göre, derlenmiş bir dilde bunu istediğiniz şekilde yapmanın "hiç" kelimesinden hiçbir yolu yoktur.

C++ böyle bir şablon sihrine sahiptir:

#include <iostream>
#include <variant>

struct A
{
    int a = 100;
    int Get() { return a; }
};

struct B :A
{
    int b = -100;
};

struct C :B
{
    int Get() { return a + b; }
};

using BaseImpl = std::variant<A, B, C>;
struct Base : BaseImpl
{
    using BaseImpl::BaseImpl;
    int Get() { return std::visit([](auto&& arg) { return arg.Get(); }, static_cast<BaseImpl&>(*this)); }
};

int main()
{
    Base a = A();
    Base b = B();
    Base c = C();
    std::cout << a.Get() << ", " << b.Get() << ", " << c.Get() << std::endl; //100, 100, 0
    b = C();
    std::cout << a.Get() << ", " << b.Get() << ", " << c.Get() << std::endl; //100, 0, 0
    return 0;
}
 
Vladimir Simakov #:

Herhangi bir fonksiyonun .text segmentinde adresi vardır.

Herhangi bir üye işlev (yöntem) bu işaretçiyi dolaylı olarak ilk parametresi olarak kabul eder.

Statik yöntemler bu işaretçiyi kabul etmez ve esasen sözdizimsel "şeker" olup fiilen sıradan işlevlerdir.

Bir sanal fonksiyon çağrıldığında, çalıştırılabilir fonksiyonun adresi sanal fonksiyon tablosundan alınır, bu tablonun işaretçisi sanal fonksiyonun bildirildiği sınıfta örtük olarak bulunur. Yürütülebilir fonksiyonun işaretçisinin başlatılması, nesnenin bir örneği oluşturulurken gerçekleşir, mantık şu şekildedir (tüm acemilere açık hale getirmek için mql ile yazıyorum:

Doğal olarak, gerçekte böyle değildir, ancak işleve işaretçinin başlatılması mekanizması tam olarak böyledir.

Örnekli detaylı açıklama için teşekkürler!

 
Vladimir Simakov #:

Senin bu konudaki fikrin nedir?

Eğer arayüzlerin olasılıkları hakkındaki pişmanlığımdan bahsediyorsanız. Sınıflara/yapılara yalnızca sözdizimsel kısıtlamalar getirmek istiyorum. Yani, sadece derleme aşamasında, aynı const değiştiricisinde olduğu gibi. Kısacası öz denetim için.

Derlenmiş bir dilde istediğinizi yapmanın "hiç" kelimesinden yola çıkarak bir yolu yok.

Yukarıda bir koltuk değneği yazdım. Bu tür durumlar için zaten yerleşik bir şey olsun istedim.

 

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi üzerine forum

MetaTrader 5 yapı 3950'nin yeni sürümü: Terminalde Para Çekme/Doldurma ve güncellenmiş işlem raporu

fxsaber, 2023.09.19 23:25

Hatalardan nasıl kurtulurum?
#define  TEMPNAME(A) A##__LINE__
#define  TEMPNAME2(A) Tmp##A
   
void OnStart()
{
  int TEMPNAME(Tmp); // variable 'Tmp__LINE__' not used
  
  int TEMPNAME2(__LINE__); // 'Tmp__LINE__' - variable already defined
  int TEMPNAME2(__LINE__); // variable 'Tmp__LINE__' not used
}
#define  TEMPNAME2(A) Tmp##A
#define  TEMPNAME1(A) TEMPNAME2(A)
   
void OnStart()
{
  int TEMPNAME1(__LINE__);
  int TEMPNAME1(__LINE__);
}

İlk kez __LINE__/__COUNTER__ işaretlerin içine metin olarak, ikinci kez ise sayı olarak aktarılır.

 
Muhtemelen bir bisiklet icat etmiştir, bilmiyorum. Daha zarif çözümler bilen varsa lütfen paylaşsın.

Önceden (eski derleyici yapılarında) bir sınıfı bildiriminden önce kullanmak mümkündü:
class A;

class B
{
   public: A a;
   public: int Val;
};

class A
{
   public: B * b;
   public: int Test() {return b.Val + 1;}
};

//+------------------------------------------------------------------+
//|                                                                                |
//+------------------------------------------------------------------+
void OnStart()
{
   B b;
   b.a.b = GetPointer(b);
   b.Val = 1;
   
   Print(b.a.Test());
}
Ama şimdi derlerken bir hata alıyoruz:
tanımlanmamış sınıf 'A' kullanılamaz

Bu hatayı aşmak için iki çözüm buldum.

1. Temel sınıf aracılığıyla:

class A0
{
   public: virtual int Test() {return 0;}
};

class B
{
   public: A0 * a;
   public: int Val;
};

class A: public A0
{
   public: A(B * source) {b = source;}
   public: B * b;
   public: virtual int Test() {return b.Val + 1;}
};

//+------------------------------------------------------------------+
//|                                                                                |
//+------------------------------------------------------------------+
void OnStart()
{
   B b;
   A a(GetPointer(b));
   
   b.a = GetPointer(a);
   b.Val = 1;
   
   Print(b.a.Test());
}

2. İç içe geçmiş bir sınıf aracılığıyla:

class B
{
   class A
   {
      public: B * b;
      public: int Test() {return b.Val + 1;}
   };

   public: A a;
   public: int Val;
};

//+------------------------------------------------------------------+
//|                                                                                |
//+------------------------------------------------------------------+
void OnStart()
{
   B b;
   b.a.b = GetPointer(b);
   b.Val = 1;
   
   Print(b.a.Test());
}

Bana göre ikinci çözüm birincisinden daha uygun.