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

 
Vladislav Boyko #:

Правильно ли я понимаю, что спецификатор delete нет смысла использовать, если может быть использована ссылка/указатель на базовый класс? Или в таких случаях необходимо закрытое наследование? 

class Base
  {
public:
   void method() { Print(__FUNCSIG__); }
  };

class Foo : public Base
  {
   void method() = delete;
  };

void OnStart()
  {
   Foo foo;
   f(foo);
  }

void f(Base &b)
  {
   b.method();
  }


Интересный пример )) 

Насколько понимаю, компилятор видит, что в качестве параметра ему передали class Foo & { ... }, но при вызове ::method() всё равно обращается к методу родительского класса, как к единственному разрешённому методу. Что неудивительно, с одной стороны. С другой, как бы легально обходим запрет, созданный с помощью delete. Получается, что спецификатор delete работает только при явном указании типа. Т.е. вот так уже не получится:

void f(Foo &b)
   {
   b.method();
   }

Ошибка: attempting to reference deleted function 'void Foo::method()' 

Таким образом, в первом случае, когда параметр Base, мы сталкиваемся, я бы сказал, с лайтовым ограничением. А во втором, когда параметр Foo, - с жёстким.

Vladislav Boyko #:

...Как принято поступать?

Наверное принято поступать так, как того требует решаемая задача...

 
Denis Kirichenko #:
Насколько понимаю, компилятор видит, что в качестве параметра ему передали class Foo & { ... }, но при вызове ::method() всё равно обращается к методу родительского класса, как к единственному разрешённому методу. Что неудивительно, с одной стороны. С другой, как бы легально обходим запрет, созданный с помощью delete. Получается, что спецификатор delete работает только при явном указании типа. Т.е. вот так уже не получится:

Интересно, что с виртуальным методом будет ошибка на этапе компиляции. А с обычным - просто вызов метода базового класса.

class Base
  {
public:
   virtual void method() { Print(__FUNCSIG__); }
  };

class Foo : public Base
  {
   void method() = delete; // function 'Foo::method' must have a body
  };

void OnStart()
  {
   Foo foo;
   f(foo);
  }

void f(Base &b)
  {
   b.method();
  }

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

 
Vladislav Boyko #:

При закрытом наследовании тоже геморой - придется для других публичных методов что-то такое городить:

В общем, не до конца понимаю логику использования delete в этом контексте.

Умные дядьки предлагают для "чистого кода" наследоваться, вместо того, чтобы править существующий оттестированный код. Ага, легко сказать.

Хотя, вероятно, я просто изначально наплужил с архитектурой.

Все это нормальное поведение в этом контексте наследования. Какие умники? Принцип OCP очень хорош, но НЕ связан с наследованием.

Какую реальную проблему вы пытаетесь решить?

Вероятно, вам следует использовать композицию вместо наследования.

 
Alain Verleyen #:
Какие умники?

Я когда-то слышал утверждение, подобное тому, что я написал (что лучше унаследоваться, чем править существующий код). Но я не помню, где я это "слышал". Возможно, я что-то неправильно понял или моя память исказила информацию. Вероятно, наследование хорошо там, где его возможность изначально предусмотрена архитектурой.

Alain Verleyen #:
Какую реальную проблему вы пытаетесь решить?

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

 
Vladislav Boyko # :

Я когда-то слышал утверждение, подобное тому, что я написал (что лучше унаследоваться, чем править существующий код). Но я не помню, где я это "слышал". Возможно, я что-то неправильно понял или моя память исказила информацию. Вероятно, наследование хорошо там, где его возможность изначально предусмотрена архитектурой.

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

"=delete" НЕ предназначено и не должно использоваться для изменения открытого интерфейса в контексте наследования. Это плохая практика, открытый интерфейс в иерархии классов следует уважать и следовать принципу Лисков.

По этой же причине его нельзя использовать с виртуальными функциями, так как это изменит «контракт» виртуального интерфейса.

(Надеюсь, перевод этих концепций ООП на русский язык понятен).

 
Alain Verleyen #:

"=delete" НЕ предназначено и не должно использоваться для изменения открытого интерфейса в контексте наследования. Это плохая практика, открытый интерфейс в иерархии классов следует уважать и следовать принципу Лисков.

По этой же причине его нельзя использовать с виртуальными функциями, так как это изменит «контракт» виртуального интерфейса.

(Надеюсь, перевод этих концепций ООП на русский язык понятен).

Теперь все встало на свои места. Вы ответили на мои вопросы, спасибо большое!

 
fxsaber #:
Просьба объяснить логику такого поведения компилятора.

Только что случайно нашел в закладках браузера:

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

Ошибки, баги, вопросы

Ilyas, 2024.03.11 15:50

Потому, что C++ генерирует конструктор копирования по умолчанию, а MQL5 нет (пока/до сих пор).

Т.к. в вашем коде отсуствует конструктор копирования, то для возвращаемого объекта из "оператора копирования", вызывается: "конструктор по умолчанию" + "оператор копирования".

Получается рекурсия:
"оператор копирования" = "конструктор по умолчанию" + "оператор копирования".

На сколько я понимаю (могу ошибаться): MQL не генерирует неявный конструктор копирования, а неявный operator= не знает, что делать с константным полем.

 
Vladislav Boyko # :

Только что случайно нашел в закладках браузера:

На сколько я понимаю (могу ошибаться): MQL не генерирует неявный конструктор копирования, а неявный  operator= не знает, что делать с константным полем.

Точно, не знал такого поведения компилятора MQL, спасибо. Так что это не ошибка, как я сказал, а ограничение.

Это также объясняется в книге , см. раздел «Конструктор копирования».

Учебник по MQL5: Объектно-Ориентированное Программирование / Классы и интерфейсы / Конструкторы: по умолчанию, параметрический, копирования
Учебник по MQL5: Объектно-Ориентированное Программирование / Классы и интерфейсы / Конструкторы: по умолчанию, параметрический, копирования
  • www.mql5.com
Мы уже сталкивались с конструкторами в главе, посвященной структурам (см. раздел Конструкторы и деструкторы ). Для классов они работают, во многом...
 

Подскажите, пожалууйста, почему терминал ByBIT показывает противоположную картину? Или совсем косячит


Вот терминал МТ5 от любого известного форекс-брокера


КОробка - линия. Так должно быть. 


А вот терминал МТ5 BYBIT


Линия куда-то влево уезжает. 


МТ5 терминалы по разному работают с графикой???

 
Ivan Butko #:

Подскажите, пожалууйста, почему терминал ByBIT показывает противоположную картину? Или совсем косячит


Вот терминал МТ5 от любого известного форекс-брокера


КОробка - линия. Так должно быть. 


А вот терминал МТ5 BYBIT


Линия куда-то влево уезжает. 


МТ5 терминалы по разному работают с графикой???

кто-ж знает как вы рисовали "коробку" и линию..

а причины отличий могут быть :

время ? в смысле что разные смещения GMT 

бары..в смысле опять-же время, но открытия/начала баров