MQL5 Компилятор не различает класс и указатель на него - страница 5

 
Знак = копируте область памяти одного объекта в область памяти другого объекта. Все объекты остаются где и были. 
 
Vladimir Simakov:
Да не вызовешь его никак. Чистая утечка памяти.

Делайте так, что бы можно было вызывать.

 

Кстати, господа разработчики, тут все таки лучше поправить. Как никак new действительно возвращает указатель, поэтому добавьте проверку, что на другом конце = тоже указатель, уберите здесь неявное приведение (А) new A();, как я понял - именно это и происходит.

 
Vladimir Simakov:

Кстати, господа разработчики, тут все таки лучше поправить. Как никак new действительно возвращает указатель, поэтому добавьте проверку, что на другом конце = тоже указатель, уберите здесь неявное приведение (А) new A();, как я понял - именно это и происходит.

Там идет вызов этого оператора

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

MQL5 Компилятор не различает класс и указатель на него

fxsaber, 2019.01.10 06:36

С каких времен определены (вопрос разработчикам)

void A::operator =( const A& );
void A::operator =( const A* );

и как они работают? Следующий компилируемый код выглядит бредово

    A* b = NULL;    
    m_A[1] = b;    


Грубо говоря, он выглядит так

class A
{
public:
    int iValue;
    
    void operator =( const A* Ptr )
    {
      Print(__FUNCSIG__);
      
      this.iValue = Ptr.iValue;
    }
};
//......................
A m_A[2];

void OnStart()
{
A a;

    m_A[0] =a; 
    m_A[1] = new A();
}
 
fxsaber:

Там идет вызов этого оператора


Грубо говоря, он выглядит так

Да понял я. Неплохие такие грабли получились. Кстати, в С++ этой перегрузки оператора = нет, VS ругается.
 

Странная тема, однако.  Прежде чем поднимать шум, неплохо было бы ознакомиться, что в MQL всю жизнь указатели неявно кастились к объектам (разыменовывались), это удобно и все к этому привыкли. Вместо трудночитаемых записей  a()->b()->c()->d() можно писать в привычном ООП формате:  a().b().c().d(),  и меньше лишних преобразований делать в процессе передачи в функции.  А теперь из-за чьего-то недовольства всё менять?

 
Alexey Navoykov:

Странная тема, однако.  Прежде чем поднимать шум, неплохо было бы ознакомиться, что в MQL всю жизнь указатели неявно кастились к объектам (разыменовывались), это удобно и все к этому привыкли. Вместо трудночитаемых записей  a()->b()->c()->d() можно писать в привычном ООП формате:  a().b().c().d(),  и меньше лишних преобразований делать в процессе передачи в функции.  А теперь из-за чьего-то недовольства всё менять?

Дело не в кастинге. Вы не вникли.

 

Если ориентироваться на заявленный прообраз MQL - С++.

В С++ оператор new возвращает указатель, соответственно, если m_A - массив объектов:

m_A[1] = new A();

здесь была бы ошибка типа.

Вот эта строка пропускалась бы компилятором:

m_A[1] = *( new A() );

Но вызывала бы утечку памяти.


Было бы неплохо, если бы в MQL было такое же поведение.

 
Alexey Navoykov:

Странная тема, однако.  Прежде чем поднимать шум, неплохо было бы ознакомиться, что в MQL всю жизнь указатели неявно кастились к объектам (разыменовывались), это удобно и все к этому привыкли. Вместо трудночитаемых записей  a()->b()->c()->d() можно писать в привычном ООП формате:  a().b().c().d(),  и меньше лишних преобразований делать в процессе передачи в функции.  А теперь из-за чьего-то недовольства всё менять?

А если в деталях на простых примерах.

A a;

// 'a' ожидает объект
 
a = new A(); // а ему дают указатель, ведь можно же

// что в MQL равнозначно?
a = *(A*) new A();

По итогу имеем

1. 'а' получает копию созданного объекта, указатель на созданный new объект теряется

2. что будет в 'a' если new не удстся создать объект/выделить память?

Второй случай (наоборот)

A* a; // глобальный указатель - 'a' ожидает указатель на объект

// далее всё происходит внутри некой функции
A b; // создаем второй в стеке (ну типа в стеке, не суть)

a =b;
// т.е. тут объект "неявно кастится" к указателю?)
a = &b;

1. после выхода из функции, 'b' как локальный объект должен быть разрушен. 

на что тогда будет ссылаться 'a'?

2. или всё таки сработает оператор копирования и 'b' будет скопирован по указателю 'a' ? а если 'a' не был до этого определен?

 
SemenTalonov:

Второй случай (наоборот)

A* a; // глобальный указатель - 'a' ожидает указатель на объект

// далее всё происходит внутри некой функции
A b; // создаем второй в стеке (ну типа в стеке, не суть)

a =b;
// т.е. тут объект "неявно кастится" к указателю?)


Тут наоборот - указатель a неявно кастится к объекту (разыменовывается), и затем к нему применятся оператор=.  Вчера fxsaber также упоминал об этом.

И вот в этом случае я соглашусь, что такое поведение лучше запретить.  Хоть по логике оно не противоречит правилам MQL (т.к. вызов оператора= равносилен вызову любого другого метода объекта), но это приводит к неоднозначности восприятия такого кода и трудноуловимым ошибкам. И это касается не только оператора=, но также == и !=, как минимум.  А возможно и для других операторов нужно запретить такой кастинг.  Потому как в C++ к операторам можно применять: +-<>[].

Короче вердикт такой:   при применении к указателю операторов, которые в C++ разрешены для указателей, запретить неявный кастинг этого указателя к объекту.  Соответственно в вышеприведённом примере будет ошибка компиляции.

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