Nello stesso libro di testo, il codice è venuto fuori:
#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); // ошибка, закрытый метод базового класса не доступен в потомках
Strana cosa il costruttore:
public: //--- конструктор класса доступен всем
CBaseClass(){m_member=5;return;};
Perché c'è un operatore di ritorno qui?
È la prima volta che vedo questo operatore usato nel costruttore. Infatti, il costruttore viene chiamato automaticamente. E ci sarà comunque un'uscita. Questo operatore ha senso nel costruttore?
Nello stesso libro di testo, il codice è venuto fuori:
Strana cosa il costruttore:
Perché c'è un operatore di ritorno qui?
È la prima volta che vedo questo operatore usato nel costruttore. Infatti, il costruttore viene chiamato automaticamente. E ci sarà comunque un'uscita. Questo operatore ha senso nel costruttore?
Non è necessario in questo esempio, ma ci può essere un'inizializzazione complessa quando è necessaria un'uscita anticipata.
Il costruttore e il distruttore sono funzioni normali. Solo il costruttore e il distruttore di default sono chiamati automaticamente. Gli altri sono chiamati dall'utente.
Il libro di testo dà questo esempio in relazione al polimorfismo:
//--- Базовый класс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);}//площадь квадрата
};
C'è una cosa che non capisco. Se usiamo gli oggetti funzione figli per le chiamate, cioè i metodi derivati CCircle e CSquare, allora l'area GetArea() può essere calcolata bypassando le dichiarazioni nella classe base. Cioè non creare affatto funzioni virtuali nella classe base, e nei metodi derivati creare un semplice metodo e basta! Allora perché abbiamo bisogno di una funzione virtuale?
È interessante vedere un esempio adeguato e logico, dove si può vedere che le funzioni virtuali forniscono qualche beneficio. Perché quello che ho visto non era logico, almeno per me. Vorrei capire lo stesso.
Il libro di testo dà questo esempio in relazione al polimorfismo:
C'è una cosa che non capisco. Se usiamo gli oggetti funzione figli per le chiamate, cioè i metodi derivati CCircle e CSquare, allora l'area GetArea() può essere calcolata bypassando le dichiarazioni nella classe base. Cioè non creare affatto funzioni virtuali in una classe base, e nei metodi derivati creare un semplice metodo e basta! Allora perché abbiamo bisogno di una funzione virtuale?
È interessante vedere un esempio adeguato e logico, dove si può vedere che le funzioni virtuali forniscono qualche beneficio. Perché quello che ho visto non era logico, almeno per me. Vorrei capire lo stesso.
Questo è il campione più semplice per capire il polimorfismo. Per ottenerlo rapidamente.
Ci sono casi complicati. Lo applicherete quando ne avrete bisogno. Non ha senso preoccuparsi ora. Quando il compito è terminato, ci si deve pensare.
Per esempio, ho una classe base con tutte le possibili interfacce di lettura/scrittura. Ha anche metodi virtuali privati (2 in totale - lettura/scrittura), che collegano questa interfaccia nella classe base con le classi derivate. In realtà le classi derivate possono essere qualsiasi dove c'è lavoro con i file (file, mappatura, canali, internet). Ogni classe derivata definisce questi metodi virtuali in modo diverso, ma tutte le classi hanno la stessa interfaccia della classe base.
Il libro di testo dà questo esempio in relazione al polimorfismo:
C'è una cosa che non capisco. Se usiamo gli oggetti funzione figli per le chiamate, cioè i metodi derivati CCircle e CSquare, allora l'area GetArea() può essere calcolata bypassando le dichiarazioni nella classe base. Cioè non creare affatto funzioni virtuali nella classe base, e nei metodi derivati creare un semplice metodo e basta! Allora perché abbiamo bisogno di una funzione virtuale?
È interessante vedere un esempio adeguato e logico, dove si può vedere che le funzioni virtuali forniscono qualche beneficio. Perché quello che ho visto non era logico, almeno per me. Voglio capirlo lo stesso.
Cercherò di abbozzare un piccolo campione:
#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;
}
Grazie a questa struttura, non avremo bisogno di entrare nell'algoritmo di lavoro, che può essere molto grande e complesso (tutto è semplificato qui), avremo solo bisogno di aggiungere un altro discendente, m3 in enumerazione e un altro caso in switch. Cioè, abbiamo unificato i dati di input, il che eviterà la modifica nella parte principale del programma.
Naturalmente, questo sarà appropriato solo se l'algoritmo di lavoro accetta una varietà di tipi come input. Se c'è solo un tipo, tutto questo è inutile.
Il libro di testo dà questo esempio in relazione al polimorfismo:
C'è una cosa che non capisco. Se usiamo gli oggetti funzione figli per le chiamate, cioè i metodi derivati CCircle e CSquare, allora l'area GetArea() può essere calcolata bypassando le dichiarazioni nella classe base. Cioè non creare affatto funzioni virtuali in una classe base, e nei metodi derivati creare un semplice metodo e basta! Allora perché abbiamo bisogno di una funzione virtuale?
È interessante vedere un esempio adeguato e logico, dove si può vedere che le funzioni virtuali forniscono qualche beneficio. Perché quello che ho visto non era logico, almeno per me. Vorrei capire lo stesso.
Ecco un semplice esempio:
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();
}
Usiamo la funzione GetArea() senza sapere per quale forma viene chiamata.
//---- SetColorBySend
TradingFunc::SetColorBySend (constcolor fc_ColorSendBuy, // Цвет открытия ордера на покупкуconstcolor fc_ColorSendSell) // Цвет открытия ордера на продажу
{
ColorBySend [2] = {fc_ColorSendBuy, fc_ColorSendSell};
}
Il compilatore generalmente combatte questa assegnazione di elementi all'arrayColorBySend in questo modo:
Con che cosa ha a che fare questo? È davvero necessario assegnare valori elemento per elemento? Non è possibile farlo come lista? A cosa è legato? Dopo tutto, è così che funziona il compito anche nel libro di testo...
Il compilatore giura su questa assegnazione di elementi all'array ColorBySend in generale come questa:
Con che cosa ha a che fare questo? È davvero necessario assegnare valori elemento per elemento? Non è possibile farlo come lista? Cosa c'entra? Dopo tutto, è così che si fa l'assegnazione anche nel libro di testo...
Un costrutto del tipo {qualcosa, qualcos'altro} può essere solo un array di costanti. Ma vengono sostituiti i parametri passati nella funzione che sono in realtà variabili locali della funzione. Il modificatore const in questo caso non ha alcun significato, poiché indica solo che il valore passato non può essere modificato. Come risultato
{fc_ColorSendBuy, fc_ColorSendSell}
è un'espressione di variabile che il compilatore non può capire. Ahimè.
i nomi dei parametri non sono importanti... i nomi diversi hanno senso affinché qualcosa non sia confuso con qualcosa...
Potete scrivere alcuni valori nella dichiarazione della funzione,
e altri valori nella funzione stessa
o si possono nominare i parametri in modo identico ovunque, a seconda di ciò che è più conveniente per chi scrive il codice
Nello stesso libro di testo, il codice è venuto fuori:
Strana cosa il costruttore:
Perché c'è un operatore di ritorno qui?È la prima volta che vedo questo operatore usato nel costruttore. Infatti, il costruttore viene chiamato automaticamente. E ci sarà comunque un'uscita. Questo operatore ha senso nel costruttore?
Nello stesso libro di testo, il codice è venuto fuori:
Strana cosa il costruttore:
Perché c'è un operatore di ritorno qui?È la prima volta che vedo questo operatore usato nel costruttore. Infatti, il costruttore viene chiamato automaticamente. E ci sarà comunque un'uscita. Questo operatore ha senso nel costruttore?
Non è necessario in questo esempio, ma ci può essere un'inizializzazione complessa quando è necessaria un'uscita anticipata.
Il costruttore e il distruttore sono funzioni normali. Solo il costruttore e il distruttore di default sono chiamati automaticamente. Gli altri sono chiamati dall'utente.
Il libro di testo dà questo esempio in relazione al polimorfismo:
C'è una cosa che non capisco. Se usiamo gli oggetti funzione figli per le chiamate, cioè i metodi derivati CCircle e CSquare, allora l'area GetArea() può essere calcolata bypassando le dichiarazioni nella classe base. Cioè non creare affatto funzioni virtuali nella classe base, e nei metodi derivati creare un semplice metodo e basta! Allora perché abbiamo bisogno di una funzione virtuale?
È interessante vedere un esempio adeguato e logico, dove si può vedere che le funzioni virtuali forniscono qualche beneficio. Perché quello che ho visto non era logico, almeno per me. Vorrei capire lo stesso.
Il libro di testo dà questo esempio in relazione al polimorfismo:
C'è una cosa che non capisco. Se usiamo gli oggetti funzione figli per le chiamate, cioè i metodi derivati CCircle e CSquare, allora l'area GetArea() può essere calcolata bypassando le dichiarazioni nella classe base. Cioè non creare affatto funzioni virtuali in una classe base, e nei metodi derivati creare un semplice metodo e basta! Allora perché abbiamo bisogno di una funzione virtuale?
È interessante vedere un esempio adeguato e logico, dove si può vedere che le funzioni virtuali forniscono qualche beneficio. Perché quello che ho visto non era logico, almeno per me. Vorrei capire lo stesso.
Questo è il campione più semplice per capire il polimorfismo. Per ottenerlo rapidamente.
Ci sono casi complicati. Lo applicherete quando ne avrete bisogno. Non ha senso preoccuparsi ora. Quando il compito è terminato, ci si deve pensare.
Per esempio, ho una classe base con tutte le possibili interfacce di lettura/scrittura. Ha anche metodi virtuali privati (2 in totale - lettura/scrittura), che collegano questa interfaccia nella classe base con le classi derivate. In realtà le classi derivate possono essere qualsiasi dove c'è lavoro con i file (file, mappatura, canali, internet). Ogni classe derivata definisce questi metodi virtuali in modo diverso, ma tutte le classi hanno la stessa interfaccia della classe base.
Il libro di testo dà questo esempio in relazione al polimorfismo:
C'è una cosa che non capisco. Se usiamo gli oggetti funzione figli per le chiamate, cioè i metodi derivati CCircle e CSquare, allora l'area GetArea() può essere calcolata bypassando le dichiarazioni nella classe base. Cioè non creare affatto funzioni virtuali nella classe base, e nei metodi derivati creare un semplice metodo e basta! Allora perché abbiamo bisogno di una funzione virtuale?
È interessante vedere un esempio adeguato e logico, dove si può vedere che le funzioni virtuali forniscono qualche beneficio. Perché quello che ho visto non era logico, almeno per me. Voglio capirlo lo stesso.
Cercherò di abbozzare un piccolo campione:
Grazie a questa struttura, non avremo bisogno di entrare nell'algoritmo di lavoro, che può essere molto grande e complesso (tutto è semplificato qui), avremo solo bisogno di aggiungere un altro discendente, m3 in enumerazione e un altro caso in switch. Cioè, abbiamo unificato i dati di input, il che eviterà la modifica nella parte principale del programma.
Naturalmente, questo sarà appropriato solo se l'algoritmo di lavoro accetta una varietà di tipi come input. Se c'è solo un tipo, tutto questo è inutile.
Il libro di testo dà questo esempio in relazione al polimorfismo:
C'è una cosa che non capisco. Se usiamo gli oggetti funzione figli per le chiamate, cioè i metodi derivati CCircle e CSquare, allora l'area GetArea() può essere calcolata bypassando le dichiarazioni nella classe base. Cioè non creare affatto funzioni virtuali in una classe base, e nei metodi derivati creare un semplice metodo e basta! Allora perché abbiamo bisogno di una funzione virtuale?
È interessante vedere un esempio adeguato e logico, dove si può vedere che le funzioni virtuali forniscono qualche beneficio. Perché quello che ho visto non era logico, almeno per me. Vorrei capire lo stesso.
Ecco un semplice esempio:
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(); }Usiamo la funzione GetArea() senza sapere per quale forma viene chiamata.Ho questo setter in una classe:
Il compilatore generalmente combatte questa assegnazione di elementi all'array ColorBySend in questo modo:
'fc_ColorSendBuy' - constant expression required TradingFunc.mqh 91 23 'fc_ColorSendSell' - constant expression required TradingFunc.mqh 91 40 '{' - expression expected TradingFunc.mqh 91 22Con che cosa ha a che fare questo? È davvero necessario assegnare valori elemento per elemento? Non è possibile farlo come lista? A cosa è legato? Dopo tutto, è così che funziona il compito anche nel libro di testo...Ho questo setter in una classe:
Il compilatore giura su questa assegnazione di elementi all'array ColorBySend in generale come questa:
Con che cosa ha a che fare questo? È davvero necessario assegnare valori elemento per elemento? Non è possibile farlo come lista? Cosa c'entra? Dopo tutto, è così che si fa l'assegnazione anche nel libro di testo...{fc_ColorSendBuy, fc_ColorSendSell}è un'espressione di variabile che il compilatore non può capire. Ahimè.