Ошибки, баги, вопросы - страница 1183

 
Zeleniy:

При тестировании советника, выдает ошибку

invalid takeprofit for OrderSend function

OrderSend error 4107

Как можно исправить не влезая в код советника?

в настройках попробуйте увеличить или уменьшить тейкпрофит
 
mql5:
Для данного объекта нельзя использовать функцию ZeroMemory

Ясно. Но почему компилятор показывает эту ошибку не в месте использования ZeroMemory, а в месте объявления класса?  Сбивает с толку. Я уже всю голову сломал, пытаясь понять в чём ошибка, и где находится.  Вы уж, пожалуйста, сделайте чтоб ошибка выдавалась в нужном месте.  Ведь например при копировании объекта, содержащего неразрешённые для копирования элементы, ошибка возникает именно в строчке с копированием, а не где-то внутри класса.

 
meat:

Если перейти к практической стороне всего этого, то мне уже пришлось столкнуться с проблемой. В коде использовались статические объекты.  Потом я решил заменить некоторые из них на динамические.  В итоге операции сравнения и присваивания стали работать совсем по другому. И эту проблему было сложно выявить, т.к. программа продолжает нормально компилироваться и работать, но не так, как надо.

Не сразу понял суть проблемы

class B {};

class A {
public:
        bool operator !=( A* a ) { Print( __FUNCTION__ ); return ( true  );  }
        bool operator !=( B* b ) { Print( __FUNCTION__ ); return ( false );  }
        bool operator >>( A* a ) { Print( __FUNCTION__ ); return ( true  );  }
        bool operator +( A* a )  { Print( __FUNCTION__ ); return ( false  ); }
        bool operator !()        { Print( __FUNCTION__ ); return ( true   ); }
};

void OnStart()
{
        A *a = new A;
        B *b = new B;
        if ( a != a ) Print( "1" );
        if ( a != b ) Print( "2" );
        if ( a >> a ) Print( "3" );
        if ( !a )     Print( "4" );
        delete( a );
        delete( b );
}
Отсюда видно, что (a != a) приводит к сравнению указателей, в то время как (a >> a) приводит к вызову operator >>( A* )

Налицо противоречие.

Изменить поведение (a >> a) нельзя как и других перегруженных операторов (кроме == и !=), поскольку это сделает невозможным следующую конструкцию, поскольку нельзя вернуть (A), а можно вернуть только (A*). 

class A {
public:
        A *operator >>( string str ) { return ( GetPointer( this ) ); }
};

void OnStart()
{
        A *a = new A;
        a << "1234" << "мы" << "всю ночь" << "тусили"; //множественное применение оператора <<
}

Также невозможно будет полноценно пользоваться перегруженными операторами ввиду отсутствия операции приведения указателя к объекту (*a)

Остается только изменить поведение (== и !=)

Для сравнения указателей (== и !=) между собой и с числом\нулем (поскольку иные операции с указателями лишены смысла) необходимо ввести специальную функцию наподобие (GetPointer) или явно указать компилятору приведение типа

void OnStart()
{
        A *a = new A;
        B *b = new B;
        if ( ulong(a) != ulong(b) ) Print( "2" ); //хочу сравнить указатели
         if (       a  !=       b  ) Print( "2" ); //хочу вызвать operator !=( B* )

}

Таким образом сохранится возможность полноценного использования перегруженных операторов и будет устранено указанное выше противоречие

Единственным разумным исключением из общего правила должен остаться operator=(), поскольку


class A {
public:
        A *operator =( A* a ) { return ( GetPointer( this ) ); }
};
void OnStart()
{
        A *a = new A;
        a = a; //не должно трактоваться компилятором как вызов operator=( A* ),
                // а должно остаться как присваивание указателю значения
}
 
Ну и конечно предложение использовать (*a) хотя бы для операторов - вернуться к записи принятой в С++ 
class A {
public:
        bool operator !=( A* a ) { Print( __FUNCTION__ ); return ( true  );  }
};

void OnStart()
{
        A *a = new A;
        if (  a !=  a ) Print( 1 ); //сравнение указателей
        if ( *a != *a ) Print( 2 ); //вызов operator !=( A* )
}

разом бы устранило все противоречия.

Исправлюсь: на самом деле противоречия устраняются только частично, поскольку при такой записи (*a) не решается проблема множественного применения операторов (что сейчас успешно работает со всеми операторами, кроме == и !=) - поэтому лучшим вариантом для сравнения указателей между собой на равенство\неравенство остается использование специальной функции - или явное приведение к типу ulong

 
A100, спасибо за сообщения, разберёмся.
 
Ошибка компиляции
class A {
public:
      A( int a1 ) : a3( a1 ) { }
  static int a2;
        int a3;
};
int A::a2 = 1;

void OnStart()
{
        int b = A::a2;  //нормально
        A t1( b );     //нормально
        A t2( A::a2 ); //ошибка компиляции
        A* t3 = new A( A::a2 ); //нормально
}
если статический член аргумент конструктора (кроме new)
 
Компилятор не дает комментировать внутри #define после переноса
#define f( x )                   \
        ( x != 0 &&  /*comment*/\ 
          x != 1 )

так нормально, а так

#define f( x )       \
        ( x != 0 &&  \ /*comment*/
          x != 1 )
ошибка компиляции
 

В продолжение темы об указателях, хорошо бы добавить в MQL стандартный оператор взятия указателя '&', так было бы значительно удобнее и компактнее, нежели громоздкий GetPointer.  Да и отпадает необходимость приведения с помощью ulong, о чём шла речь выше.  Таким образом, имея в арсенале операторы * и &,  мы сможем однозначно определять требуемые операции:

if (&a==&b) Print("Указатели равны");
if (*a==*b) Print("Объекты равны");


И ещё по поводу этого амперсанда. Очень не хватает в MQL ссылок на переменные. Особенно с учётом ограниченного применения указателей (только на объекты классов).  Часто требуется доступ к глубоко вложенному элементу структуры или многомерного массива.  Приходится каждый раз писать полный путь к нему, это очень загромождает код.   С помощью создания ссылки можно всё упростить.   Да и вообще бывает необходимо локально "поменять" имя какой-то переменной для удобства.  Впрочем, что я тут объясняю. Удобства пользования ссылок и так всем известны.  А сейчас вместо этого приходится использовать #define, что конечно очень нехорошо.

Ну и также нужна возможность передачи результата функции по ссылке,  т.е.  double& Func() { } 

 

В последнее время в Facebook появились задвоения публикаций из блогов:

1 

 
meat:

В продолжение темы об указателях, хорошо бы добавить в MQL стандартный оператор взятия указателя '&', так было бы значительно удобнее и компактнее, нежели громоздкий GetPointer.  Да и отпадает необходимость приведения с помощью ulong, о чём шла речь выше.  Таким образом, имея в арсенале операторы * и &,  мы сможем однозначно определять требуемые операции:

Если принять обращение к функциям-членам только через (*a), то это не даст явных преимуществ, а наоборот - приведет к невозможности простого и понятного множественного применения операторов.

class A {
public:
        A *operator >>( string str ) { Print( __FUNCTION__); return ( GetPointer( this ) ); }
};

void OnStart()
{
        A *a = new A;
        a << "1234" << "мы" << "всю ночь" << "тусили"; //простая и понятная запись

попробуйте переписать это с учетом Вашего предложения

void OnStart()
{
        A *a = new A;
        *(*(*(*a << "1234") << "мы") << "всю ночь") << "тусили"; //запутанная запись
}

А вместо указателя использовать сам объект нельзя, поскольку operator <<(...) может вернуть только указатель на объект.

Какие операции с указателями не лишены смысла? - только сравнение между собой и с числом - следовательно ими необходимо пренебречь, отдав их в специальную функцию (например bool ComparePointer( a,b)) ради сохранения возможности множественного применения операторов без чего собственно сама перегрузка операторов теряет основной смысл.

Причина обращения: