Учёба. Классы. Нужна помощь. - страница 19

 
Yuriy Bykov #:

Мне кажется, имеется недопонимание. Если брать ваш пример с переопределением метода CTrade::OrderSend() в двух потомках CStatTrade и CStopStatTrade, где в каждом выполняются какие-то дополнительные действия, а затем вызывается метод родительского класса, то внутри кода этих методов вы обязаны будете указать, метод какого родителя вы вызываете. Объявление этого метода виртуальным никак не освободит вас от этого. Про вызов этого метода снаружи кода класса речи не шло, только: "... сможете вызвать из классов потомков".

Это дальше уже зависит от того, как мы заменим в коде объект CTrade объектом CStopStatTrade. Если без внесения неопределённости, то и без объявления виртуальным получим, что вызываться будет метод именно из CStopStatTrade. А если создадим новый объект класса  CStopStatTrade, но указатель на него запомним в переменной, объявленной как CTrade*, то тогда метод должен быть виртуальным, чтобы вызвалась именно версия потомка, а не CTrade.

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

Да, в моем примере - явно указать приходится.  Это как раз, на мой взгляд, допустимое решение - когда мы перегружаем функцию, добавляем в неё свой функционал, а затем - вызываем функцию предка. 

И верно отмечено, что такое явное указание - именно "снаружи" объекта лучше избегать. 

 

При том, что для использования виртуальности нужно использовать указатели (исключение), как в Вашем примере, в частности.

 
Georgiy Merts #:

Да, чаще всего это так.

Однако, не всегда.

Смотри:

У тебя есть класс фигуры, и в нём функция, получающая её диаметр.   Плодишь кучу потомков от этого класса. Разных фигур. 

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

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

Заметь - никаких указателей нет. 

Здесь речь идет про вызов через указатель на базовый класс. Если же напрямую через объект потомка, то это видится мне слишком очевидным примером использования. Зачет.

 
Alexey Viktorov #:

Вот такими объяснениями, простите загажены, все учебники и примеры. Это ни о чём. Мне кажется это легко решается обычной перегрузкой функции… Это не утверждение, могу и заблуждаться…

Перегрузка делается программистом вручную, виртуальные функции вызываются через таблицу вирт. ф-й на автомате самой системой.

 
Alexey Volchanskiy #:

Перегрузка делается программистом вручную, виртуальные функции вызываются через таблицу вирт. ф-й на автомате самой системой.

Охрененно "понятное" объяснение.
Хотите сказать, что виртуальные функции не пишутся программистом? Или, что невиртуальные не вызываются системой?
 
Yuriy Bykov #:
Виталий, я, конечно, извиняюсь, но то, что вы написали, не имеет ничего общего с механизмом виртуальных функций. Кнопки на форме не являются разными наследниками. Если будет время, напишу подробнее позже.

Спасибо, Юрий! Вы единственный, кто нормально сказал: "Веталь, ты не прав. То, что ты написал - ошибочно".

Я создал эту ветку, чтоб получить ясность по вопросу классов. Из моих предыдущих постов видно невооружённым глазом, что в классах я новичок. Ну совершил ошибку, что тут такого? Не ошибается только бездельник. Зачем же меня за это "на копья поднимать"? Ох и народ у нас тут... Так и хочется Высоцкого процитировать....

Вообще, есть истина: чем примитивнее общество, тем более грубо оно действует и тем более жестокие наказания оно выдумывает. Может эта истина побудит кого-то призадуматься...
 
Alexey Viktorov #:

Найди пожалуйста в классе class CObject виртуальную функцию 

и объясни пожалуйста как это работает. Куда какие наследники надо писать? Что означает указатель(если я правильно понимаю) *node 

Что означает mode я примерно понимаю. Но только примерно…

Ты это серьёзно? Я же тебе всё объяснял, и ты сам всё делал потом. Ещё и примерами своими меня завалил...

 

Виртуализация


 
Georgiy Merts #:

Да, в моем примере - явно указать приходится.  Это как раз, на мой взгляд, допустимое решение - когда мы перегружаем функцию, добавляем в неё свой функционал, а затем - вызываем функцию предка. 

И верно отмечено, что такое явное указание - именно "снаружи" объекта лучше избегать. 

переопределяем (в случае с виртуальным методом)

В документации есть хороший пример, который демонстрирует разницу между этими терминами

https://www.mql5.com/ru/docs/basis/oop/virtual#override

Модификатор override означает, что объявляемая функция обязательно должна переопределить метод родительского класса. Использование этого модификатора позволяет избежать ошибок при переопределении, таких как случайное изменение сигнатуры метода. Например, в базовом классе определен метод func, принимающий в качестве аргумента переменную типа int:

class CFoo
  {
   void virtual func(int x) const { }
  };

Далее метод переопределяется в наследуемом классе:

class CBar : public CFoo
  {
   void func(short x) { }
  };

Но по ошибке тип аргумента изменяется с int на short. Фактически, в этом случае уже происходит не переопределение, а перегрузка метода. Действуя в соответствии с алгоритмом определения перегруженной функции, в определенных ситуациях компилятор может выбрать метод, определенный в базовом классе, вместо переопределенного метода.

Чтобы избежать подобных ошибок, к переопределяемому методу следует явно добавлять модификатор override.

 
Alexey Volchanskiy #:
Перегрузка делается программистом вручную

вот уж мастер примеров)) перегрузка сама подбирает по подходящим входным данным, где там что в ручную делается?

и то не могу реального применения найти, вроде энтузиазма много в голове)) 

проще в ручную прописать все, чем вызывать функцию краб с указанием во входящем сколько у него клешней, если одна то варить 3 минуты...)

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

add

когда начинаешь изучать и все вокруг - темный лес, потом кода-нибудь возвращаешься к этом, думаешь и вот на эту * рань я столько с квадратной головой ходил. Это как раз про перегрузку, шаблоны и виртуальная функция