#property copyright"Copyright 2011, MetaQuotes Software Corp."#property link"https://www.mql5.com"#property version"1.00"//+------------------------------------------------------------------+//| Класс-пример с несколькими типами доступа |//+------------------------------------------------------------------+class CBaseClass
{
private: //--- закрытый член недоступен из потомковint m_member;
protected: //--- защищенный метод доступен из базового класса и его потомковint Member(){return(m_member);}
public: //--- конструктор класса доступен всем
CBaseClass(){m_member=5;return;};
private: //--- закрытый метод для присвоения значения члену m_membervoid Member(int value) { m_member=value;};
};
//+------------------------------------------------------------------+//| Производный класс с ошибками |//+------------------------------------------------------------------+class CDerived: public CBaseClass // public наследование можно не указывать, оно по умолчанию
{
public:
void Func() // определим в потомке функцию с обращениями к членам базового класса
{
//--- попытка модификации закрытого члена базового класса
m_member=0; // ошибка, закрытый член базового класса никому не доступен
Member(0); // ошибка, закрытый метод базового класса не доступен в потомках
Странный момент в конструкторе:
public: //--- конструктор класса доступен всем
CBaseClass(){m_member=5;return;};
Зачем тут оператор return?
Я первый раз встречаю чтобы в конструкторе данный оператор использовался. Ведь по сути конструктор вызывается автоматом. И выход будет по-любому. Смысл в данному операторе в конструкторе разве есть?
Я первый раз встречаю чтобы в конструкторе данный оператор использовался. Ведь по сути конструктор вызывается автоматом. И выход будет по-любому. Смысл в данному операторе в конструкторе разве есть?
В этом примере он не нужен, но возможна сложная инициализация, когда необходим досрочный выход.
Конструктор и деструктор это обычные функции. Только конструктор по умолчанию и деструктор вызывается автоматом. Остальные пользователь вызывает.
В учебнике приводится такой пример применительно к полиморфизму:
//--- Базовый классclass CShape
{
protected:
int m_type; // тип фигурыint m_xpos; // X - координата точки привязкиint m_ypos; // Y - координата точки привязкиpublic:
void CShape(){m_type=0;}; // конструктор, тип равен нулюint GetType(){return(m_type);};// возвращает тип фигурыvirtualdouble GetArea(){return (0); }// возвращает площадь фигуры
};
//--- производный класс Кругclass CCircle : public CShape // после двоеточия указывается базовый класс,
{ // от которого производится наследование private:
double m_radius; // радиус кругаpublic:
void CCircle(){m_type=1;}; // конструктор, тип равен 1 void SetRadius(double r){m_radius=r;};
virtualdouble GetArea(){return (3.14*m_radius*m_radius);}// площадь круга
};
class CSquare : public CShape // после двоеточия указывается базовый класс,
{ // от которого производится наследование private:
double m_square_side; // сторона квадратаpublic:
void CSquare(){m_type=2;}; // конструктор, тип равен 2 void SetSide(double s){m_square_side=s;};
virtualdouble GetArea(){return (m_square_side*m_square_side);}//площадь квадрата
};
Я вот одного не понял. Если всё-таки использовать для вызовов объекты дочерник функций т.е. производных методов CCircle и CSquare, то площадь GetArea() можно вычислить минуя объявления в базовом классе. Т.е. в базовом классе не создавать виртуальные функции вообще, а в производных создать обычный метод и всё! Тогда зачем виртуальная функция нужна?
Интересно увидеть адекватный и логичный пример, где видно, что виртуальные функции дают какую-то пользу. Потому что то, что я видел, не логично, по крайне мере, для меня. Хочется понять всё-таки.
В учебнике приводится такой пример применительно к полиморфизму:
Я вот одного не понял. Если всё-таки использовать для вызовов объекты дочерник функций т.е. производных методов CCircle и CSquare, то площадь GetArea() можно вычислить минуя объявления в базовом классе. Т.е. в базовом классе не создавать виртуальные функции вообще, а в производных создать обычный метод и всё! Тогда зачем виртуальная функция нужна?
Интересно увидеть адекватный и логичный пример, где видно, что виртуальные функции дают какую-то пользу. Потому что то, что я видел, не логично, по крайне мере, для меня. Хочется понять всё-таки.
Это простейший пример для понимания полиморфизма. Чтобы быстро дошло.
Бывают сложные случаи. Когда понадобится, применишь. Сейчас нет смысла заморачиваться. Будет задача, тогда надо думать.
Например, есть у меня базовый класс со всеми возможными интерфейсами чтения/записи. В нём же есть приватные виртуальные методы (всего 2 - чтение/запись), которые связывают этот интерфейс в базовом классе с производными классами. Собственно, призводные классы могут быть любые, где есть работа с файлами (файлы, маппинг, каналы, интернет). Каждый из производных классов определяет по-своему эти виртуальные методы, но у всех классов одинаковый интерфейс из базового класса.
В учебнике приводится такой пример применительно к полиморфизму:
Я вот одного не понял. Если всё-таки использовать для вызовов объекты дочерник функций т.е. производных методов CCircle и CSquare, то площадь GetArea() можно вычислить минуя объявления в базовом классе. Т.е. в базовом классе не создавать виртуальные функции вообще, а в производных создать обычный метод и всё! Тогда зачем виртуальная функция нужна?
Интересно увидеть адекватный и логичный пример, где видно, что виртуальные функции дают какую-то пользу. Потому что то, что я видел, не логично, по крайне мере, для меня. Хочется понять всё-таки.
Попробую набросать небольшой пример:
#property strict#property show_inputsenum Mes_type {
m1,
m2
};
input Mes_type mes_t; // Выберите тип сообщенияclass Message {
public:
virtualvoid action() {};
};
class Mes1 : public Message {
public:
virtualvoid action() {Alert("Типичные ошибки в программах");}
};
class Mes2 : public Message {
public:
virtualvoid action() {Alert("Оффлайновые графики");}
};
voidOnStart() {
// Формируем входные данные для какого-то алгоритма//////////////////////////////////////////
Message *mes; //switch(mes_t) //
{ //case m1: //
mes = new Mes1; //break; //case m2: //
mes = new Mes2; //
} ///////////////////////////////////////////// Рабочий алгоритм//////////////////////////////////////////
mes.action(); ////////////////////////////////////////////delete mes;
}
Благодаря такой структуре, при возможных дальнейших доработках, нам не нужно лезть в рабочий алгоритм, который может быть очень большим и сложным (здесь все упрощено), нужно будет лишь добавить еще одного наследника, m3 в перечислении и ещё один case в switch. Т.е. мы унифицировали входные данные что позволит избежать правки в главной части программы.
Конечно же это уместно только если рабочий алгоритм принимает на вход разнообразные типы. Если тип один, то все это ни к чему.
В учебнике приводится такой пример применительно к полиморфизму:
Я вот одного не понял. Если всё-таки использовать для вызовов объекты дочерник функций т.е. производных методов CCircle и CSquare, то площадь GetArea() можно вычислить минуя объявления в базовом классе. Т.е. в базовом классе не создавать виртуальные функции вообще, а в производных создать обычный метод и всё! Тогда зачем виртуальная функция нужна?
Интересно увидеть адекватный и логичный пример, где видно, что виртуальные функции дают какую-то пользу. Потому что то, что я видел, не логично, по крайне мере, для меня. Хочется понять всё-таки.
Вот простой пример:
CShape* GetNewShape()
{
if( ... ) // Здесь какое-то условие.
returnnew CCircle();
elsereturnnew CSquare();
}
CShape* M[10];
for( int i = 0; i < 10; i++ )
{
M[i] = GetNewShape();
}
double WholeArea = 0.0;
for( int i = 0; i < 10; i++ )
{
WholeArea += M[i].GetArea();
}
Мы используем функцию GetArea(), не зная, для какой фигуры она вызывается.
//---- SetColorBySend
TradingFunc::SetColorBySend (constcolor fc_ColorSendBuy, // Цвет открытия ордера на покупкуconstcolor fc_ColorSendSell) // Цвет открытия ордера на продажу
{
ColorBySend [2] = {fc_ColorSendBuy, fc_ColorSendSell};
}
Компилятор ругается в общем-то на такое присвоение элементов массивуColorBySend так:
С чем это связано? Неужели нужно поэлементно присваивать значения? Списком не возможно? С чем это связано? Ведь так даже в учебнике присваивание происходит...
Компилятор ругается в общем-то на такое присвоение элементов массиву ColorBySend так:
С чем это связано? Неужели нужно поэлементно присваивать значения? Списком не возможно? С чем это связано? Ведь так даже в учебнике присваивание происходит...
Конструкция вида {что-то, что-то еще} может быть только массивом констант. У вас же туда подставлены переданные в функцию параметры, которые по сути - локальные переменные функции. Модификатор const в данном случае не имеет значения, так как он только указывает на невозможность можификации переданной величины. В итоге
{fc_ColorSendBuy, fc_ColorSendSell}
- это переменное выражение, которое компильятор не может понять. Увы.
имена параметров не важны.. разные имена имеют смысл чтобы что-то с чем-то не перепутать..
в декларации функции можно одни значения писать,
а самой в функции другие
а можно везде одинаково параметры назвать, это как удобнее кодописатиелю
В том же учебнике попался код:
Странный момент в конструкторе:
Зачем тут оператор return?Я первый раз встречаю чтобы в конструкторе данный оператор использовался. Ведь по сути конструктор вызывается автоматом. И выход будет по-любому. Смысл в данному операторе в конструкторе разве есть?
В том же учебнике попался код:
Странный момент в конструкторе:
Зачем тут оператор return?Я первый раз встречаю чтобы в конструкторе данный оператор использовался. Ведь по сути конструктор вызывается автоматом. И выход будет по-любому. Смысл в данному операторе в конструкторе разве есть?
В этом примере он не нужен, но возможна сложная инициализация, когда необходим досрочный выход.
Конструктор и деструктор это обычные функции. Только конструктор по умолчанию и деструктор вызывается автоматом. Остальные пользователь вызывает.
В учебнике приводится такой пример применительно к полиморфизму:
Я вот одного не понял. Если всё-таки использовать для вызовов объекты дочерник функций т.е. производных методов CCircle и CSquare, то площадь GetArea() можно вычислить минуя объявления в базовом классе. Т.е. в базовом классе не создавать виртуальные функции вообще, а в производных создать обычный метод и всё! Тогда зачем виртуальная функция нужна?
Интересно увидеть адекватный и логичный пример, где видно, что виртуальные функции дают какую-то пользу. Потому что то, что я видел, не логично, по крайне мере, для меня. Хочется понять всё-таки.
В учебнике приводится такой пример применительно к полиморфизму:
Я вот одного не понял. Если всё-таки использовать для вызовов объекты дочерник функций т.е. производных методов CCircle и CSquare, то площадь GetArea() можно вычислить минуя объявления в базовом классе. Т.е. в базовом классе не создавать виртуальные функции вообще, а в производных создать обычный метод и всё! Тогда зачем виртуальная функция нужна?
Интересно увидеть адекватный и логичный пример, где видно, что виртуальные функции дают какую-то пользу. Потому что то, что я видел, не логично, по крайне мере, для меня. Хочется понять всё-таки.
Это простейший пример для понимания полиморфизма. Чтобы быстро дошло.
Бывают сложные случаи. Когда понадобится, применишь. Сейчас нет смысла заморачиваться. Будет задача, тогда надо думать.
Например, есть у меня базовый класс со всеми возможными интерфейсами чтения/записи. В нём же есть приватные виртуальные методы (всего 2 - чтение/запись), которые связывают этот интерфейс в базовом классе с производными классами. Собственно, призводные классы могут быть любые, где есть работа с файлами (файлы, маппинг, каналы, интернет). Каждый из производных классов определяет по-своему эти виртуальные методы, но у всех классов одинаковый интерфейс из базового класса.
В учебнике приводится такой пример применительно к полиморфизму:
Я вот одного не понял. Если всё-таки использовать для вызовов объекты дочерник функций т.е. производных методов CCircle и CSquare, то площадь GetArea() можно вычислить минуя объявления в базовом классе. Т.е. в базовом классе не создавать виртуальные функции вообще, а в производных создать обычный метод и всё! Тогда зачем виртуальная функция нужна?
Интересно увидеть адекватный и логичный пример, где видно, что виртуальные функции дают какую-то пользу. Потому что то, что я видел, не логично, по крайне мере, для меня. Хочется понять всё-таки.
Попробую набросать небольшой пример:
Благодаря такой структуре, при возможных дальнейших доработках, нам не нужно лезть в рабочий алгоритм, который может быть очень большим и сложным (здесь все упрощено), нужно будет лишь добавить еще одного наследника, m3 в перечислении и ещё один case в switch. Т.е. мы унифицировали входные данные что позволит избежать правки в главной части программы.
Конечно же это уместно только если рабочий алгоритм принимает на вход разнообразные типы. Если тип один, то все это ни к чему.
В учебнике приводится такой пример применительно к полиморфизму:
Я вот одного не понял. Если всё-таки использовать для вызовов объекты дочерник функций т.е. производных методов CCircle и CSquare, то площадь GetArea() можно вычислить минуя объявления в базовом классе. Т.е. в базовом классе не создавать виртуальные функции вообще, а в производных создать обычный метод и всё! Тогда зачем виртуальная функция нужна?
Интересно увидеть адекватный и логичный пример, где видно, что виртуальные функции дают какую-то пользу. Потому что то, что я видел, не логично, по крайне мере, для меня. Хочется понять всё-таки.
Вот простой пример:
CShape* GetNewShape() { if( ... ) // Здесь какое-то условие. return new CCircle(); else return new CSquare(); } CShape* M[10]; for( int i = 0; i < 10; i++ ) { M[i] = GetNewShape(); } double WholeArea = 0.0; for( int i = 0; i < 10; i++ ) { WholeArea += M[i].GetArea(); }Мы используем функцию GetArea(), не зная, для какой фигуры она вызывается.У меня есть вот такой вот Сеттер в классе:
Компилятор ругается в общем-то на такое присвоение элементов массиву ColorBySend так:
'fc_ColorSendBuy' - constant expression required TradingFunc.mqh 91 23 'fc_ColorSendSell' - constant expression required TradingFunc.mqh 91 40 '{' - expression expected TradingFunc.mqh 91 22С чем это связано? Неужели нужно поэлементно присваивать значения? Списком не возможно? С чем это связано? Ведь так даже в учебнике присваивание происходит...У меня есть вот такой вот Сеттер в классе:
Компилятор ругается в общем-то на такое присвоение элементов массиву ColorBySend так:
С чем это связано? Неужели нужно поэлементно присваивать значения? Списком не возможно? С чем это связано? Ведь так даже в учебнике присваивание происходит...{fc_ColorSendBuy, fc_ColorSendSell}- это переменное выражение, которое компильятор не может понять. Увы.