Вопрос. Можно ли после объявления в родительском классе виртуальной функции с определённым набором параметров и их типов изменять в классах-потомках количество и типы параметров у соответствующих виртуальных функций?
С одной стороны, в Справочнике говорится, что "виртуальная функция может замещаться в производном классе. Выбор того, какое определение функции вызвать для виртуальной функции, происходит динамически (на этапе выполнения). Типичный случай – когда базовый класс содержит, а производные классы имеют свои версии этой функции". С другой стороны, приведённые в Справочнике примеры касаются случаев, когда у виртуальных функций различаются тела определения функций, а не заголовки определения функций.
На сколько помню можно. Но нужно абсолютно жоское различие в типах и количестве параметров.
Также следует быть осторожным с тими передаваемых значений и дефаултными значениями.
Такой нет (верней может ипрокатит, но при багах и определенных оговорках)
//Ели второй параметр будет упущен, то компилятор может и не "понять" смысла всего задуманного
boll MyFunction(int Param);
boll MyFunction(int Param1,int Param2 = 0);
//Так тоже может не прокатить по причине совпадения типов у второго параметра
boll MyFunction(int Param1,color Param2);
boll MyFunction(int Param1,int Param2);
Точно такая же фигня творится если происходит ПЕРЕЗАГРУЗКА методов внутри класса.
mql5: Только точная копия определения, за исключением параметров по умолчанию (умолчания могут отличаться, но лучше это не использовать)
Вы имеете в виду "только точную копию заголовка определения"? Ведь определение функции включает в себя заголовок плюс тело. Тела в примерах точно различаются.
Interesting, как я понял, виртуализация функций и перегрузка функций - немного разные вещи. И вот mql5 говорит, что при виртуализации функций должна быть жёсткая копия заголовка функции(параметры по умолчанию в расчет не беру).
Interesting, как я понял, виртуализация функций и перегрузка функций - немного разные вещи. И вот mql5 говорит, что при виртуализации функций должна быть жёсткая копия заголовка функции(параметры по умолчанию в расчет не беру).
> Вопрос. Можно ли после объявления в родительском классе виртуальной функции с определённым набором параметров и их типов изменять в классах-потомках количество и типы параметров у соответствующих виртуальных функций?
Если я все правильно понимаю то потомок должен перегрузить функционал предка.
Честно говоря я не помню делал или нет подобные вещи с виртуальными (кажется делал), но про перегрузку утверждение верно - сам наступил однажды на эти грабли.
PS
Если все делать правильно, то как я понимаю, количество параметров можно как увеличивать так и уменьшать. Сложности будут если если количество параметров останется прежним, но изменятся их типы...
class C_A //родительский класс
{
public:
virtualdouble function(double a1, double a2, double a3) { return; }
}
class C_B : public C_A
{
public:
virtualdouble function(double a1, double a2, double a3) { return(a1); }
}
class C_C : public C_A
{
public: virtualdouble function(double a1, double a2, double a3) { return(a2); }
double function(double a1, double a2) { return(a1+a2); }
}
//где-то в программе объявляем указатель
C_A *pointer;
int random=rand()%2;
switch(random)
{
case0: pointer=new C_B; break;
case1: pointer=new C_C; break;
}
//вызываем виртуальный методif(pointer!=NULL)
{
pointer.function(a1,a2,a3);
}
Получается, что независимо от того, перегружен или нет метод function в классе С_С, виртуальная функция может быть вызвана только с тремя параметрами - pointer.function(a1,a2,a3). Соответственно, до двухпараметного метода из класса С_С программа при вызове виртуальных функций никогда не доберётся. Правильно?
Получается, что независимо от того, перегружен или нет метод function в классе С_С, виртуальная функция может быть вызвана только с тремя параметрами - pointer.function(a1,a2,a3). Соответственно, до двухпараметного метода из класса С_С программа при вызове виртуальных функций никогда не доберётся. Правильно?
Проанализируйте что делает программа вставив в конструкторы и дестректоры принты с макросом __FUNCTION__, будет очень полезно.
От себя же добавлю что объявляя указатель базового класса вы тем самым строите "тонельный" проход к потомкам через базовый класс. Таким образом компилятор при таком вызове потомков будет видеть у потомков только функции объявленные в базовом классе. Если же вы (даже в пределах одной программы) объявите напрямую объект потомка то в нём будут доступны все функции.
class C_A //родительский класс
{
public:
virtualdouble function(double a1, double a2, double a3) { return; }
}
class C_B : public C_A
{
public:
virtualdouble function(double a1, double a2, double a3) { return(a1); }
}
class C_C : public C_A
{
public:
virtualdouble function(double a1, double a2, double a3) { return(a2); }
double function(double a1, double a2) { return(a1+a2); }
}
//где-то в программе объявляем указатель
C_A *pointer;
int random=rand()%2;
switch(random)
{
case0: pointer=new C_B; break;
case1: pointer=new C_C; break;
//вызываем виртуальный методif(pointer!=NULL)
{
pointer.function(a1,a2,a3);
}
C_С *new_pointer=new C_C;
new_pointer.function(a1,a2);
Получается, что независимо от того, перегружен или нет метод function в классе С_С, виртуальная функция может быть вызвана только с тремя параметрами - pointer.function(a1,a2,a3). Соответственно, до двухпараметного метода из класса С_С программа при вызове виртуальных функций никогда не доберётся. Правильно?
Из собственного опыта могу порекомендовать так комплектовать код
А в качестве примера и развлечения можете посмотреть вложенный файл.
С указателями и new было вазиться не охота, поэтому просто объявил рабочий класс как переменную.
Советник по таймеру через равные промежутки времени генерирует случайное число 0/1 и в зависимости от результата выполняет одну из двух функций: MarketBuy / MarketSell.
Вопрос. Можно ли после объявления в родительском классе виртуальной функции с определённым набором параметров и их типов изменять в классах-потомках количество и типы параметров у соответствующих виртуальных функций?
С одной стороны, в Справочнике говорится, что "виртуальная функция может замещаться в производном классе. Выбор того, какое определение функции вызвать для виртуальной функции, происходит динамически (на этапе выполнения). Типичный случай – когда базовый класс содержит, а производные классы имеют свои версии этой функции". С другой стороны, приведённые в Справочнике примеры касаются случаев, когда у виртуальных функций различаются тела определения функций, а не заголовки определения функций.
На сколько помню можно. Но нужно абсолютно жоское различие в типах и количестве параметров.
Также следует быть осторожным с тими передаваемых значений и дефаултными значениями.
Для простоты приведу примеры.
Такой вариант прокатит
Такой нет (верней может ипрокатит, но при багах и определенных оговорках)
Точно такая же фигня творится если происходит ПЕРЕЗАГРУЗКА методов внутри класса.
Только точная копия определения, за исключением параметров по умолчанию (умолчания могут отличаться, но лучше это не использовать)
Interesting, как я понял, виртуализация функций и перегрузка функций - немного разные вещи. И вот mql5 говорит, что при виртуализации функций должна быть жёсткая копия заголовка функции(параметры по умолчанию в расчет не беру).
Interesting, как я понял, виртуализация функций и перегрузка функций - немного разные вещи. И вот mql5 говорит, что при виртуализации функций должна быть жёсткая копия заголовка функции(параметры по умолчанию в расчет не беру).
> Вопрос. Можно ли после объявления в родительском классе виртуальной функции с определённым набором параметров и их типов изменять в классах-потомках количество и типы параметров у соответствующих виртуальных функций?
Если я все правильно понимаю то потомок должен перегрузить функционал предка.
Честно говоря я не помню делал или нет подобные вещи с виртуальными (кажется делал), но про перегрузку утверждение верно - сам наступил однажды на эти грабли.
PS
Если все делать правильно, то как я понимаю, количество параметров можно как увеличивать так и уменьшать. Сложности будут если если количество параметров останется прежним, но изменятся их типы...
В общем, набросал вот такой пример:
Получается, что независимо от того, перегружен или нет метод function в классе С_С, виртуальная функция может быть вызвана только с тремя параметрами - pointer.function(a1,a2,a3). Соответственно, до двухпараметного метода из класса С_С программа при вызове виртуальных функций никогда не доберётся. Правильно?
В общем, набросал вот такой пример:
Получается, что независимо от того, перегружен или нет метод function в классе С_С, виртуальная функция может быть вызвана только с тремя параметрами - pointer.function(a1,a2,a3). Соответственно, до двухпараметного метода из класса С_С программа при вызове виртуальных функций никогда не доберётся. Правильно?
Проанализируйте что делает программа вставив в конструкторы и дестректоры принты с макросом __FUNCTION__, будет очень полезно.
От себя же добавлю что объявляя указатель базового класса вы тем самым строите "тонельный" проход к потомкам через базовый класс. Таким образом компилятор при таком вызове потомков будет видеть у потомков только функции объявленные в базовом классе. Если же вы (даже в пределах одной программы) объявите напрямую объект потомка то в нём будут доступны все функции.
В общем, набросал вот такой пример:
Получается, что независимо от того, перегружен или нет метод function в классе С_С, виртуальная функция может быть вызвана только с тремя параметрами - pointer.function(a1,a2,a3). Соответственно, до двухпараметного метода из класса С_С программа при вызове виртуальных функций никогда не доберётся. Правильно?
Из собственного опыта могу порекомендовать так комплектовать код
А в качестве примера и развлечения можете посмотреть вложенный файл.
С указателями и new было вазиться не охота, поэтому просто объявил рабочий класс как переменную.
Советник по таймеру через равные промежутки времени генерирует случайное число 0/1 и в зависимости от результата выполняет одну из двух функций: MarketBuy / MarketSell.
Можно было при желании и вот так объявить
Но тогда может баг вылезти по поводу конфликта с
PS
Делал на скорую руку, поэтому могут быть определенные неточности.
Но в принципе основную идею понять можно.
Спасибо огромное за ценные советы и указания! Обязательно воспользуюсь, только б времени хватило и на теорию, и на практику.
Из собственного опыта могу порекомендовать так комплектовать код
Почему именно так? В чём подводный камень кроется?
Когда-то были проблемы вроде с этим. Но какие сейчас и не вспомню.
В общем привык так.
Обычно разницы конечно нет, по крайней мере в моем примере пробовал местами менять, все прокатило...
Когда-то были проблемы вроде с этим. Но какие сейчас и не вспомню.