Классы mql взаимодействие

4 февраля 2021 г. 4:46

Приведу простой пример взаимодействия классов в mql4, их атрибутов, конструкторов и копи-конструкторов copy constructor. Особенно пример будет полезен тем, кто никогда не сталкивался с C-подобными языками программирования (C++, C#, java).

Сразу сообщу, что в этой статье не будут расписаны все моменты работы с классами. Только простой пример для того, чтобы быстро начать использовать классы для более гибкого написания кода. Полный текст программы в конце статьи.
Также я не придерживался принятого стиля написания кода mql, так как я привык оформлять код как в python и считаю принятое оформление кода менее читабельным. Да простят меня mql-разработчики!

Допустим, в некоторые переменные нужно сохранить данные о сотрудниках некоторой компании, а затем вывести имя директора, например так:

Employee mike("Mike", "Director");
Employee denis("Denis", "Designer");

company.add_employee(mike);
company.add_employee(denis);

director = company.get_director();
Print("Director name is " + director.name);

Можно сохранять данную информацию проще. Во второй версии программы вы увидите, как это можно сделать.

Код программы находится на github:
https://github.com/vivazzi/mql_examples/blob/master/classes/Classes.mq4

1 версия

Создадим класс Employee, который сохраняет имя сотрудника в поле name и его должность в поле post:

class Employee {
public:
    string name;
    string post;

    // По умолчанию, объявленные переменные имеют значение NULL, поэтому нет необходимости 
    // в конструкторе без параметров к каждой переменной присваивать NULL. Но сам конструктор без параметров нужно добавить.
    // Далее вы увидите зачем нам конструктор без параметров и зачем я рассказал про NULL 
    Employee(){};

    // при создании объекта класса Employee будем сохранять имя (name) и должность (post)
    Employee(string _name, string _post) {
        name = _name;
        post = _post;
    };

    // данная конструкция, так называемая copy constructor, позволяет создавать копию объекта.
    // Это позволяет не только копировать объекты, но и различным сторонним функциям других классов возвращать объект класса Employee
    Employee::Employee(const Employee &_employee) {
        name = _employee.name;
        post = _employee.post;
    }
};

Employee employees[2];  // объявим, что у нас два сотрудника в компании. Позже улучшим код для динамического добавления сотрудников

Хочу заметить, что в копи-конструкторе Employee::Employee(const Employee &_employee)  приходится снова дублировать логику работы конструктора, иначе в возвращаемом (копируемом) объекте не присвоются поля объекта класса. Давайте теперь ниже опишем класс Company, чтобы лучше понять, зачем нам копи-конструктор:

class Company {
public:
    Employee get_director() {
        for (int i=0; i < ArraySize(employees); i++) {
            // если у сотрудника должность Директор, то возвратить данного сотрудника
            if (employees[i].post == "Director") return employees[i];  
        }

        return Employee();
    }
};

Заметьте, если бы у нас не было копи-конструктора Employee, то компилятор выдал бы ошибку:

error: object of cannot be returned, copy constructor not found

Обратите внимание, что в mql4 нет возможности возвратить NULL в случае если совпадении по должности Director нет, так как язык mql4 является строго типизированным. Поэтому, мы должны возвратить "пустого" сотрудника, то есть объект класса Employee без значений в полях name и post, а если точнее говорить, то со значениями NULL. Для этого в классе Employee добавлен конструктор без тела , а в функции get_director(), если нет сотрудника с указанной должностью, то возвращаем Employee с пустыми скобками: так автоматически создастся Employee со значениями NULL в полях  name и post. Это как раз нам и нужно, например, чтобы сравнить, есть ли у Employee имя, и если есть, то производим дальнейшую обработку, например, показываем имя через Print. Вот оставшаяся часть кода, где можно теперь записать и использовать наши объекты классов:

int OnInit(){
    employees[0] = Employee("Mike", "Director");
    employees[1] = Employee("Denis", "Designer");

    Company company;
    Employee director;
    director = company.get_director();

    if (director.name != NULL) Print("Director name is " + director.name);
    else Print("There is not director in company");

    // можно и не создавать переменную director, а использовать company.get_director().name:
    Print("Director name is " + company.get_director().name);

    return(INIT_SUCCEEDED);
}

Итоговый вариант кода:

class Employee {
public:
    string name;
    string post;

    Employee(){};

    Employee(string _name, string _post) {
        name = _name;
        post = _post;
    };

    Employee::Employee(const Employee &_employee) {
        name = _employee.name;
        post = _employee.post;
    }
};

Employee employees[2];


class Company {
public:
    Employee get_director() {
        for (int i=0; i < ArraySize(employees); i++) {
            // если у сотрудника должность Директор, то возвратить данного сотрудника
            if (employees[i].post == "Director") return employees[i];  
        }

        return Employee();
    }
};

int OnInit(){
    employees[0] = Employee("Mike", "Director");
    employees[1] = Employee("Denis", "Designer");

    Company company;
    Employee director;
    director = company.get_director();

    if (director.name != NULL) Print("Director name is " + director.name);
    else Print("There is not director in company");

    Print("Director name is " + company.get_director().name);

    return(INIT_SUCCEEDED);
}

Версия 2

Теперь, когда код первой версии работает и наглядно понятен, можно сделать более гибкую версию записи данных:

class Employee {
public:
    string name;
    string post;

    Employee(){};

    Employee(string _name, string _post) {
        name = _name;
        post = _post;
    };

    Employee::Employee(const Employee &_employee) {
        name = _employee.name;
        post = _employee.post;
    }

};


class Company {
public:
    Employee employees[];

    void set_employees(Employee &_employees[]){
        ArrayResize(employees, ArraySize(_employees));
        for (int i=0; i < ArraySize(employees); i++) {
            employees[i] = _employees[i];
        }
    }

    void add_employee(Employee &_employee){
        ArrayResize(employees, ArraySize(employees) + 1);
        employees[ArraySize(employees) - 1] = _employee;
    }

    void add_employee(string name, string post){
        ArrayResize(employees, ArraySize(employees) + 1);
        employees[ArraySize(employees) - 1] = Employee(name, post);
    }

    Employee get_employee_by_post(string post) {
        for (int i=0; i < ArraySize(employees); i++) {
            if (employees[i].post == post) return employees[i];
        }
        return Employee();
    }

    Employee get_director() {
        return get_employee_by_post("Director");
    }

    int employee_number() {
        return ArraySize(employees);
    }

    string display_employees() {
        string res = "";

        for (int i=0; i < ArraySize(employees); i++) {
            res += employees[i].name;
            if (i <  ArraySize(employees) - 1) res += ", ";
        }

        return res;
    }
};


int OnInit(){
    Company company;

    // можем добавлять сотрудников, передав массив сотрудников
    Employee employees[2];
    employees[0] = Employee("Alla", "Manager");
    employees[1] = Employee("Bella", "Manager");
    company.set_employees(employees);

    // или можем добавить одного сотрудника
    Employee nataly("Nataly", "Manager");
    company.add_employee(nataly);

    // или можно добавить сотудников через передачу аргументов name и post
    company.add_employee("Mike", "Director");
    company.add_employee("Denis", "Designer");

    Print("Number of employees is " + (string)company.employee_number() + ": " + company.display_employees());

    Print("Director name is " + company.get_director().name);

    Employee dancer;
    dancer = company.get_employee_by_post("Dancer");
    if (dancer.name != NULL) Print("Dancer name is " + dancer.name);
    else Print("There is not dancer in company");

    return(INIT_SUCCEEDED);
}

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

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

Код программы находится на github:
https://github.com/vivazzi/mql_examples/blob/master/classes/Classes.mq4

Оцените статью

0 из 5 (всего 0 оценок)

captcha
Поля, отмеченные звёздочкой ( * ) , являются обязательными.

Спасибо за ваш отзыв!

После нажатия кнопки "Отправить" ваше сообщение будет доставлено мне на почту.

Автор статьи

Мальцев Артём

Веб-разработчик, владеющий знаниями языка программирования Python, фреймворка Django, системы управления содержимым сайта Django CMS, платформы для создания интернет-магазина Django Shop и многих различных приложений, использующих эти технологии.

Права на использование материала, расположенного на этой странице https://vivazzi.pro/it/class-mql/:

Разрешается копировать материал с указанием её автора и ссылки на оригинал без использования параметра rel="nofollow" в теге <a>. Использование:

Автор статьи: Мальцев Артём
Ссылка на статью: <a href="https://vivazzi.pro/it/class-mql/">https://vivazzi.pro/it/class-mql/</a>

Подробнее: Правила использования сайта

Комментариев: 0

Вы можете оставить комментарий как незарегистрированный пользователь.

Но зарегистрировавшись, вы сможете:

  • получать оповещения об ответах
  • просматривать свои комментарии
  • иметь возможность использовать все функции разработанных сервисов

Для комментрирования от своего имени, войдите или зарегистрируйтесь обычным способом или через социальные сети:

Отправить

На данный момент нет специального поиска, поэтому я предлагаю воспользоваться обычной поисковой системой, например, Google, добавив "vivazzi" после своего запроса.

Попробуйте

Выберите валюту для отображения денежных единиц