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

 
Vasiliy Sokolov:
Очень круто и главное идеологически правильно. Двумя руками за! 
Тогда идеологически правильнее было бы в случае
class A { public:
        bool operator !=( A* ) {}
        bool operator  <( A* ) {}
};
void f()
{
    A *a1, *a2;
    a1 != a2; //здесь простое сравнение указателей вместо вызова operator !=()
    a1 <  a2; //здесь вызывается operator <()
}
чтобы вызывался operator!=(), а не выполнялось бы сравнение указателей на равенство как это происходит сейчас. А сравнение указателей можно было бы осуществлять специальной функцией подобной ::GetPointer(...)

Но этого не делается по той простой причине что принесет значительные неудобства, а преимуществом будет лишь идеологическая правильность 

 
Давно не получал обновлений: MetaTrader5 build 1159 (подключен к MetaQuotes-Demo). Командный компилятор загружается build 1162
 
Vasiliy Sokolov:

Тогда и string - это набор конкретных чисел. И картинка - это тоже число и электрический импульс на микросхеме...

В общем учите электротехнику, коллега. 

Можно привести такое сравнение указателей в С++ и дескрипторов в MQL/C# и некоторых других языках.

Задача - хочется пообщаться в живую с приятелем.

1. Указатели. Мы знаем улицу, номер дома и квартиру. Едем на адрес, будим приятеля, достаем пузырь, он бурно радуется, общаемся ))

2. Дескрипторы. Точного адреса не знаем, вход в дом посторонним запрещен, например, это здание ФСБ. В доме есть пропускной пункт, который отказывается сказать адрес по фамилии приятеля (по дескриптору), отказывается пустить в дом (в адресное пространство). Охрана звонит приятелю и просит его выйти. Он выходит, вы радостно достаете пузырь, он шипит, - ты что!!! убери немедленно!!! Вот и погуляли...Идя домой с непочатой бутылкой в руке, вы пронзительно понимаете, что дескрипторы обеспечивают безопасность в обмен на возможности указателей.

 
Vasiliy Sokolov:

В общем учите электротехнику, коллега. 

Других аргументов нет?
 
A100:
Других аргументов нет?
А у Вас?
 
A100:
У меня есть фрагменты кода где указатели явно преобразуются к числам (для сопряжения со внешними системами запись\чтение, а также при анализе ошибок и отладке), если это будет запрещено то понизится гибкость и придется переделывать.
Аргумент интересный, требуется время на подумать. Создайте пожалуйста заявку, обсудим подробнее.
 

Кстати, а как насчёт введения в MQL операторов * и & для возможности явного обращения к объекту в первом случае, и взятия указателя объекта во втором (вместо громоздкого GetPointer).   Причём звёздочка необходима просто позарез.  Её заменить в языке нечем.  Без этого невозможно контролировать такие ситуации, как привёл A100 чуть выше, что вместо самих объекта производятся какие-то действия с указателями.  Лично для меня это постоянная проблема, приходится всегда быть начеку, либо везде явно указывать  A.operator=(B),  A.operator!=(B), т.е. теряется лаконичность, и перегрузка операторов фактически лишается смысла.

Я как-то уже поднимал эту проблему, но тема заглохла.  Давайте уже добьём этот вопрос наконец.

 

Вопрос по extern переменным.

Столкнулся с ситуацией, когда extern переменная меняется в ходе выполнения программы, но при смене таймфрейма опять принимает значение, заданное в окне свойств. Например, если перед запуском я установлю значение TradeEnable в EnableAll, а при выполнении программы поменяю значение на EnableBuy, то при перещелкивании чарта на другой таймфрейм значение вернется на EnableAll. Значение я определяю в событии таймера и вывожу через Comment, ошибки быть не может.

enum ETradeEnable {EnableAll, EnableBuy, EnableSell, DisableAll};
extern ETradeEnable TradeEnable = EnableAll;

Перещелкивание между чартами никак на переменную TradeEnable не влияет. Читаю хелп - В отличии input-переменных, значения extern-переменных могут быть программно изменены в процессе работы программы.

Вот так у меня устроены OnDeinit и OnInit.

Вопрос: я чего-то не понимаю или изменение TradeEnable это ошибка runtime?

int LastDeinitReason = 0;

void OnDeinit(const int reason)
{
    LastDeinitReason = reason;
    if(reason==REASON_CHARTCHANGE || reason==REASON_TEMPLATE || reason==REASON_PARAMETERS)
        return;
    EventKillTimer();
// далее код при завершении работы советника
}

int OnInit()
{
    if(LastDeinitReason==REASON_CHARTCHANGE || LastDeinitReason==REASON_TEMPLATE)
    {
        LastDeinitReason = 0;
        return(INIT_SUCCEEDED);
    }
    if(LastDeinitReason==REASON_PARAMETERS)
    {
        SetParams();
        return(INIT_SUCCEEDED);                              
    }
// далее код инициализации при запуске
}
 
Alexey Navoykov:

Давайте уже добьём этот вопрос наконец.

Там жертву приносятся два оператора (== и !=) ради сохранения всех остальных.

Я вижу выход в шаблоне 

template<typename T1, typename T2>
bool IsEqualPointer( const T1 *t1, const T2 *t2 )
{
    return ( ulong(t1) == ulong(t2) );
}

Тогда если operator==(!=) определен, то будет вызываться он. Если не определен, то будут сравниваться на равенство указатели. А если operator==(!=) определен и необходимо сравнить на равенство указатели, то это можно сделать при помощи указанного шаблона.

Изменения в существующую систему - минимальны и главное не затронут тех, кто просто сравнивает указатели на равенство не перегружая operator==(!=)

 
A100:

Там жертву приносятся два оператора (== и !=) ради сохранения всех остальных.

Я вижу выход в шаблоне 

Тогда если operator==(!=) определен, то будет вызываться он. Если не определен, то будут сравниваться на равенство указатели. А если operator==(!=) определен и необходимо сравнить на равенство указатели, то это можно сделать при помощи указанного шаблона.

Изменения в существующую систему - минимальны и главное не затронут тех, кто просто сравнивает указатели не перегружая operator==(!=)

Сравнение  - это ещё полбеды. Есть ведь ещё присваивание.  Да и шаблон - это просто костыль.  Можно конечно и сравнение, и присваивание делать через отдельные функции, только смысл?  Речь о том, чтобы убедить разработчиков сделать нормальное решение.

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