#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); // ошибка, закрытый метод базового класса не доступен в потомках
Une chose étrange à propos du constructeur :
public: //--- конструктор класса доступен всем
CBaseClass(){m_member=5;return;};
Pourquoi y a-t-il un opérateur de retour ici ?
C'est la première fois que je vois cet opérateur utilisé dans le constructeur. En fait, le constructeur est appelé automatiquement. Et il y aura une sortie de toute façon. Cet opérateur a-t-il un sens dans le constructeur ?
C'est la première fois que je vois cet opérateur utilisé dans le constructeur. En fait, le constructeur est appelé automatiquement. Et il y aura une sortie de toute façon. Cet opérateur a-t-il un sens dans le constructeur ?
Elle n'est pas nécessaire dans cet exemple, mais il peut y avoir une initialisation complexe lorsque la sortie anticipée est nécessaire.
Le constructeur et le destructeur sont des fonctions normales. Seuls le constructeur et le destructeur par défaut sont appelés automatiquement. Les autres sont appelés par l'utilisateur.
Le manuel donne cet exemple en relation avec le polymorphisme :
//--- Базовый класс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);}//площадь квадрата
};
Il y a une chose que je ne comprends pas. Si nous utilisons des objets de fonction enfant pour les appels, c'est-à-dire les méthodes dérivées CCircle et CSquare, alors la zone GetArea() peut être calculée en contournant les déclarations de la classe de base. C'est-à-dire ne pas créer du tout de fonctions virtuelles dans une classe de base, et dans les méthodes dérivées créer une simple méthode et c'est tout ! Alors pourquoi avons-nous besoin d'une fonction virtuelle ?
Il est intéressant de voir un exemple adéquat et logique, où l'on peut constater que les fonctions virtuelles apportent un certain avantage. Parce que ce que j'ai vu n'était pas logique, du moins pour moi. J'aimerais tout de même le comprendre.
Le manuel donne cet exemple en relation avec le polymorphisme :
Il y a une chose que je ne comprends pas. Si nous utilisons des objets de fonction enfant pour les appels, c'est-à-dire les méthodes dérivées CCircle et CSquare, alors la zone GetArea() peut être calculée en contournant les déclarations de la classe de base. C'est-à-dire ne pas créer du tout de fonctions virtuelles dans une classe de base, et dans les méthodes dérivées créer une simple méthode et c'est tout ! Alors pourquoi avons-nous besoin d'une fonction virtuelle ?
Il est intéressant de voir un exemple adéquat et logique, où l'on peut constater que les fonctions virtuelles apportent un certain avantage. Parce que ce que j'ai vu n'était pas logique, du moins pour moi. J'aimerais tout de même le comprendre.
Il s'agit de l'exemple le plus simple pour comprendre le polymorphisme. Pour l'obtenir rapidement.
Il y a des cas compliqués. Vous l'appliquerez quand vous en aurez besoin. Il n'y a pas de raison de s'embêter maintenant. Une fois la tâche accomplie, vous devrez y réfléchir.
Par exemple, j'ai une classe de base avec toutes les interfaces de lecture/écriture possibles. Elle possède également des méthodes virtuelles privées (2 au total - lecture/écriture), qui relient cette interface dans la classe de base avec les classes dérivées. En fait, les classes dérivées peuvent être n'importe où où l'on travaille avec des fichiers (fichiers, cartographie, canaux, internet). Chacune des classes dérivées définit ces méthodes virtuelles différemment, mais toutes les classes ont la même interface que la classe de base.
Le manuel donne cet exemple en relation avec le polymorphisme :
Il y a une chose que je ne comprends pas. Si nous utilisons des objets de fonction enfant pour les appels, c'est-à-dire les méthodes dérivées CCircle et CSquare, alors la zone GetArea() peut être calculée en contournant les déclarations de la classe de base. C'est-à-dire ne pas créer du tout de fonctions virtuelles dans une classe de base, et dans les méthodes dérivées créer une simple méthode et c'est tout ! Alors pourquoi avons-nous besoin d'une fonction virtuelle ?
Il est intéressant de voir un exemple adéquat et logique, où l'on peut constater que les fonctions virtuelles apportent un certain avantage. Parce que ce que j'ai vu n'était pas logique, du moins pour moi. Je veux tout de même le comprendre.
Je vais essayer d'esquisser un petit échantillon :
#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;
}
Grâce à cette structure, nous n'aurons pas besoin d'entrer dans l'algorithme de travail, qui peut être très grand et complexe (tout est simplifié ici), nous aurons seulement besoin d'ajouter un descendant de plus, m3 dans l'énumération et un cas de plus dans le switch. C'est-à-dire que nous avons unifié les données d'entrée, ce qui évitera les modifications dans la partie principale du programme.
Bien entendu, cela ne sera approprié que si l'algorithme de travail accepte une variété de types en entrée. S'il n'y a qu'un seul type, tout cela est inutile.
Le manuel donne cet exemple en relation avec le polymorphisme :
Il y a une chose que je ne comprends pas. Si nous utilisons des objets de fonction enfant pour les appels, c'est-à-dire les méthodes dérivées CCircle et CSquare, alors la zone GetArea() peut être calculée en contournant les déclarations de la classe de base. C'est-à-dire ne pas créer du tout de fonctions virtuelles dans une classe de base, et dans les méthodes dérivées créer une simple méthode et c'est tout ! Alors pourquoi avons-nous besoin d'une fonction virtuelle ?
Il est intéressant de voir un exemple adéquat et logique, où l'on peut constater que les fonctions virtuelles apportent un certain avantage. Parce que ce que j'ai vu n'était pas logique, du moins pour moi. J'aimerais tout de même le comprendre.
Voici un exemple simple :
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();
}
Nous utilisons la fonction GetArea() sans savoir pour quelle forme elle est appelée.
//---- SetColorBySend
TradingFunc::SetColorBySend (constcolor fc_ColorSendBuy, // Цвет открытия ордера на покупкуconstcolor fc_ColorSendSell) // Цвет открытия ордера на продажу
{
ColorBySend [2] = {fc_ColorSendBuy, fc_ColorSendSell};
}
Le compilateur combat généralement cette affectation d'éléments au tableauColorBySend comme ceci :
Qu'est-ce que ça a à voir ? Est-il vraiment nécessaire d'attribuer des valeurs élément par élément ? N'est-il pas possible de le faire sous forme de liste ? A quoi est-il lié ? Après tout, c'est comme ça que le devoir fonctionne, même dans le manuel...
Le compilateur jure par cette affectation d'éléments au tableau ColorBySend en général comme ceci :
Qu'est-ce que ça a à voir ? Est-il vraiment nécessaire d'attribuer des valeurs élément par élément ? N'est-il pas possible de le faire sous forme de liste ? Qu'est-ce que ça a à voir avec ça ? Après tout, c'est comme ça que les devoirs sont faits, même dans le manuel...
Une construction du type {quelque chose, quelque chose d'autre} ne peut être qu'un tableau de constantes. Mais les paramètres passés dans la fonction y sont substitués qui sont en fait des variables locales de la fonction. Le modificateur const dans ce cas n'a aucune signification puisqu'il indique seulement que la valeur passée ne peut pas être modifiée. En conséquence,
{fc_ColorSendBuy, fc_ColorSendSell}
est une expression variable que le compilateur ne peut pas comprendre. Hélas.
les noms des paramètres ne sont pas importants... des noms différents ont un sens afin que quelque chose ne soit pas confondu avec quelque chose...
Vous pouvez écrire certaines valeurs dans la déclaration de la fonction,
et d'autres valeurs dans la fonction elle-même
ou vous pouvez nommer les paramètres de manière identique partout, selon ce qui est le plus pratique pour l'auteur du code.
Dans le même manuel, le code est apparu :
Une chose étrange à propos du constructeur :
Pourquoi y a-t-il un opérateur de retour ici ?C'est la première fois que je vois cet opérateur utilisé dans le constructeur. En fait, le constructeur est appelé automatiquement. Et il y aura une sortie de toute façon. Cet opérateur a-t-il un sens dans le constructeur ?
Dans le même manuel, le code est apparu :
Une chose étrange à propos du constructeur :
Pourquoi y a-t-il un opérateur de retour ici ?C'est la première fois que je vois cet opérateur utilisé dans le constructeur. En fait, le constructeur est appelé automatiquement. Et il y aura une sortie de toute façon. Cet opérateur a-t-il un sens dans le constructeur ?
Elle n'est pas nécessaire dans cet exemple, mais il peut y avoir une initialisation complexe lorsque la sortie anticipée est nécessaire.
Le constructeur et le destructeur sont des fonctions normales. Seuls le constructeur et le destructeur par défaut sont appelés automatiquement. Les autres sont appelés par l'utilisateur.
Le manuel donne cet exemple en relation avec le polymorphisme :
Il y a une chose que je ne comprends pas. Si nous utilisons des objets de fonction enfant pour les appels, c'est-à-dire les méthodes dérivées CCircle et CSquare, alors la zone GetArea() peut être calculée en contournant les déclarations de la classe de base. C'est-à-dire ne pas créer du tout de fonctions virtuelles dans une classe de base, et dans les méthodes dérivées créer une simple méthode et c'est tout ! Alors pourquoi avons-nous besoin d'une fonction virtuelle ?
Il est intéressant de voir un exemple adéquat et logique, où l'on peut constater que les fonctions virtuelles apportent un certain avantage. Parce que ce que j'ai vu n'était pas logique, du moins pour moi. J'aimerais tout de même le comprendre.
Le manuel donne cet exemple en relation avec le polymorphisme :
Il y a une chose que je ne comprends pas. Si nous utilisons des objets de fonction enfant pour les appels, c'est-à-dire les méthodes dérivées CCircle et CSquare, alors la zone GetArea() peut être calculée en contournant les déclarations de la classe de base. C'est-à-dire ne pas créer du tout de fonctions virtuelles dans une classe de base, et dans les méthodes dérivées créer une simple méthode et c'est tout ! Alors pourquoi avons-nous besoin d'une fonction virtuelle ?
Il est intéressant de voir un exemple adéquat et logique, où l'on peut constater que les fonctions virtuelles apportent un certain avantage. Parce que ce que j'ai vu n'était pas logique, du moins pour moi. J'aimerais tout de même le comprendre.
Il s'agit de l'exemple le plus simple pour comprendre le polymorphisme. Pour l'obtenir rapidement.
Il y a des cas compliqués. Vous l'appliquerez quand vous en aurez besoin. Il n'y a pas de raison de s'embêter maintenant. Une fois la tâche accomplie, vous devrez y réfléchir.
Par exemple, j'ai une classe de base avec toutes les interfaces de lecture/écriture possibles. Elle possède également des méthodes virtuelles privées (2 au total - lecture/écriture), qui relient cette interface dans la classe de base avec les classes dérivées. En fait, les classes dérivées peuvent être n'importe où où l'on travaille avec des fichiers (fichiers, cartographie, canaux, internet). Chacune des classes dérivées définit ces méthodes virtuelles différemment, mais toutes les classes ont la même interface que la classe de base.
Le manuel donne cet exemple en relation avec le polymorphisme :
Il y a une chose que je ne comprends pas. Si nous utilisons des objets de fonction enfant pour les appels, c'est-à-dire les méthodes dérivées CCircle et CSquare, alors la zone GetArea() peut être calculée en contournant les déclarations de la classe de base. C'est-à-dire ne pas créer du tout de fonctions virtuelles dans une classe de base, et dans les méthodes dérivées créer une simple méthode et c'est tout ! Alors pourquoi avons-nous besoin d'une fonction virtuelle ?
Il est intéressant de voir un exemple adéquat et logique, où l'on peut constater que les fonctions virtuelles apportent un certain avantage. Parce que ce que j'ai vu n'était pas logique, du moins pour moi. Je veux tout de même le comprendre.
Je vais essayer d'esquisser un petit échantillon :
Grâce à cette structure, nous n'aurons pas besoin d'entrer dans l'algorithme de travail, qui peut être très grand et complexe (tout est simplifié ici), nous aurons seulement besoin d'ajouter un descendant de plus, m3 dans l'énumération et un cas de plus dans le switch. C'est-à-dire que nous avons unifié les données d'entrée, ce qui évitera les modifications dans la partie principale du programme.
Bien entendu, cela ne sera approprié que si l'algorithme de travail accepte une variété de types en entrée. S'il n'y a qu'un seul type, tout cela est inutile.
Le manuel donne cet exemple en relation avec le polymorphisme :
Il y a une chose que je ne comprends pas. Si nous utilisons des objets de fonction enfant pour les appels, c'est-à-dire les méthodes dérivées CCircle et CSquare, alors la zone GetArea() peut être calculée en contournant les déclarations de la classe de base. C'est-à-dire ne pas créer du tout de fonctions virtuelles dans une classe de base, et dans les méthodes dérivées créer une simple méthode et c'est tout ! Alors pourquoi avons-nous besoin d'une fonction virtuelle ?
Il est intéressant de voir un exemple adéquat et logique, où l'on peut constater que les fonctions virtuelles apportent un certain avantage. Parce que ce que j'ai vu n'était pas logique, du moins pour moi. J'aimerais tout de même le comprendre.
Voici un exemple simple :
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(); }Nous utilisons la fonction GetArea() sans savoir pour quelle forme elle est appelée.J'ai ce setter dans une classe :
Le compilateur combat généralement cette affectation d'éléments au tableau ColorBySend comme ceci :
'fc_ColorSendBuy' - constant expression required TradingFunc.mqh 91 23 'fc_ColorSendSell' - constant expression required TradingFunc.mqh 91 40 '{' - expression expected TradingFunc.mqh 91 22Qu'est-ce que ça a à voir ? Est-il vraiment nécessaire d'attribuer des valeurs élément par élément ? N'est-il pas possible de le faire sous forme de liste ? A quoi est-il lié ? Après tout, c'est comme ça que le devoir fonctionne, même dans le manuel...J'ai ce setter dans une classe :
Le compilateur jure par cette affectation d'éléments au tableau ColorBySend en général comme ceci :
Qu'est-ce que ça a à voir ? Est-il vraiment nécessaire d'attribuer des valeurs élément par élément ? N'est-il pas possible de le faire sous forme de liste ? Qu'est-ce que ça a à voir avec ça ? Après tout, c'est comme ça que les devoirs sont faits, même dans le manuel...{fc_ColorSendBuy, fc_ColorSendSell}est une expression variable que le compilateur ne peut pas comprendre. Hélas.