Форум » Консультации по программированию » Как грамотно инкапсулировать стркутуры? » Ответить

Как грамотно инкапсулировать стркутуры?

hoz: Есть несколько структур с хранениями некоторых данных, типа свойства символа, свойства позиции и тд. Логично, что эти данные должны использоваться в единственном экземпляре в различных классах, которые используют члены-элементы соответствующих структур. Например, вот структура свойств позиций: // =================================================_______ СВОЙСТВА ПОЗИЦИИ _______======================================================= struct Position_Properties { datetime gdt_Expiration; // Срок истечения отложенного ордера datetime gdt_OpenTime; // Время открытия выбранной позиции double gd_OpenPrice; // Цена открытия double gd_Lots; // Объём позиции на открытие double gd_CurSL; // Текущий Stop Loss выбранной позиции double gd_NewSL; // Новый Stop Loss выбранной позиции double gd_CurTP; // Текущий Take Profit выбранной позиции double gd_NewTP; // Новый Take Profit выбранной позиции int gi_CurTicket; // Тикет выбранного ордера int gi_Type; // Тип торговой операции int gi_Slippage; // Максимально допустимое отклонение цены для рыночных ордеров int gi_Magic; // Магический номер string gs_Comment; // Комментарий string gs_Symbol; // Наименование фин. инструмента, с которым производится операция ulong gu_Duration; // Длительность позиции в секундах }; Как реализовать проект так, чтоб классы данного проекта использовали единственный экземпляр данной структуры и работали только с ним, и, если модифицировали, то только этот экземпляр? Обязательно использовать синглтоны или можно обойтись без этого? В плане синглтонов я не особо понимаю как они работают, так что, думаю, что возможно иначе как-то...

Ответов - 19, стр: 1 2 All

Scriptong: hoz пишет: Обязательно использовать синглтоны или можно обойтись без этого? В данном случае singleton вообще не нужен. Просто используйте объявление переменной данного типа один раз. Singleton - это совершенно другое направление. PS. Избегайте названий переменных в стиле "gdt", "gd", "gs". Это стиль декомпилятора. Такой стиль - это "красная тряпка" для компилятора MQL4, который может посчитать Ваши исходные коды продуктом декомпиляции. В структурах вообще не используют префиксы для переменных. Префиксы используют для глобальных переменных ("g_" - global), настроечных параметров ("i_" - input) и членов класса ("m_" - member).

hoz: Scriptong пишет: В данном случае singleton вообще не нужен. Просто используйте объявление переменной данного типа один раз. Singleton - это совершенно другое направление. А для чего тогда он нужен? Я читал, что Singleton, как раз-таки и используется, для того, чтобы контролировать тот факт, что б некоторые переменные существовали в проекте в единственном экземпляре.

Scriptong: hoz пишет: А для чего тогда он нужен? К сожалению, простого ответа на этот вопрос нет, т. к. для обоснованного (а не надуманного) использования Singleton нужны такие специфические условия, которые вот так сходу не придумаешь. Кроме того речь идет о реально больших проектах, которые ни на MQL4, ни на MQL5 не создаются (нет таких удобств IDE, которые есть в Visual Studio, к примеру). Я веду к тому, что в MQL4 и MQL5 вполне возможно проконтролировать единственное использование переменной самому программисту. Не стоит усложнять программу там, где это совершенно не нужно. В данном случае объявите переменную типа Position_Properties как static и все. Если же Вам необходимо, чтобы ни одна другая переменная не имела тип Position_Properties (хотя сама такая необходимость вызывает удивление), то для этого достаточно воспользоваться поиском по файлам проекта и найти такие переменные, удалив их впоследствии.


hoz: Scriptong пишет: PS. Избегайте названий переменных в стиле "gdt", "gd", "gs". Это стиль декомпилятора. Такой стиль - это "красная тряпка" для компилятора MQL4, который может посчитать Ваши исходные коды продуктом декомпиляции. В структурах вообще не используют префиксы для переменных. Префиксы используют для глобальных переменных ("g_" - global), настроечных параметров ("i_" - input) и членов класса ("m_" - member). Игорь, Благодарю за совет. Дело в том, что я использую данные префиксы для того, чтоб видеть какой тип переменной или метода. Как-то уже и привык... gd - тип double, gs - тип string, gdt - тип datetime, gi - тип int. Отвыкать как-то снова лопать коды.. На данный момент компилятор не говорит, что у меня декомпил, так что обожду. Отложу этот момент на потом. Тем более глаз уже привык. Scriptong пишет: В данном случае объявите переменную типа Position_Properties как static и все. Если же Вам необходимо, чтобы ни одна другая переменная не имела тип Position_Properties (хотя сама такая необходимость вызывает удивление), то для этого достаточно воспользоваться поиском по файлам проекта и найти такие переменные, удалив их впоследствии. Вы имеете в виду объявить переменную типа Position_Properties как static или сам объект данной структуры? Я вот так на данный момент написал: struct Symbol_Properties { static datetime gdt_Quote; // Время поступления последней котировки static double gda_Price [2]; // Текущие рыночные цены (0 - Bid, 1- Ask) static double gd_Spread; // Размер спреда в пунктах static double gd_Swap; // Своп static double gd_Comission; // Комиссия static double gd_Pt; // Величина одного пункта static int gi_Digits; // Количество знаков в цене после запятой static int gi_StopLevel; // Минимально-допустимый уровень стоп-лосса/тейк-профита в пунктах static int gi_FreezLevel; // Уровень заморозки ордеров в пунктах }; int Symbol_Properties::gdt_Quote; int Symbol_Properties::gda_Price; int Symbol_Properties::gd_Spread; int Symbol_Properties::gd_Swap; int Symbol_Properties::gd_Comission; int Symbol_Properties::gd_Pt; int Symbol_Properties::gi_Digits; int Symbol_Properties::gi_StopLevel; int Symbol_Properties::gi_FreezLevel; Но получается что объект не создан. Что-то не верно у меня, так?

Scriptong: hoz пишет: Но получается что объект не создан. Что-то не верно у меня, так? 1. Структура - это не класс. Вы же пытаетесь обратиться к ней, как к классу. 2. SymbolProperties - это тип данных, а перед ним зачем-то указан еще один тип данных. Нужно так: SymbolProperties symbProp; // Переменная symbProp имеет тип SymbolProperties symbProp.gdt_Quote = StringToTime("2014.08.08 12:00:35"); symbProp.gda_Price[0] = 1.36579; symbProp.gda_Price[1] = 1.36589; symbProp.gd_Spread = symbProp.gda_Price[1] - symbProp.gda_Price[0]; symbProp.gd_Swap = 0.12; symbProp.gd_Commision = 0.0; symbProp.gd_Pt = 0.00001; symbProp.gi_Digits = 5; symbProp.gi_StopLevel = 3; symbProp.gi_FreezeLevel = 0;

hoz: В общем я сделал именно так: struct Symbol_Properties { static datetime gdt_Quote; // Время поступления последней котировки static double gda_Price [2]; // Текущие рыночные цены (0 - Bid, 1- Ask) static double gd_Spread; // Размер спреда в пунктах static double gd_Swap; // Своп static double gd_Comission; // Комиссия static double gd_Pt; // Величина одного пункта static int gi_Digits; // Количество знаков в цене после запятой static int gi_StopLevel; // Минимально-допустимый уровень стоп-лосса/тейк-профита в пунктах static int gi_FreezLevel; // Уровень заморозки ордеров в пунктах }; //---- Создадим объект структуре Symbol_Properties //Symbol_Properties SSym; datetime Symbol_Properties::gdt_Quote = 0; double Symbol_Properties::gda_Price [2] = {0.0, 0.0}; double Symbol_Properties::gd_Spread = 0; double Symbol_Properties::gd_Swap = 0; double Symbol_Properties::gd_Comission = 0; double Symbol_Properties::gd_Pt = 0; int Symbol_Properties::gi_Digits = 0; int Symbol_Properties::gi_StopLevel = 0; int Symbol_Properties::gi_FreezLevel = 0; Тока вот возникает мысль. Ведь удобнее обращаться к статическим переменным структуры не по такому длинному " имени " типа: double Symbol_Properties::gd_Pt = 0; А гораздо удобнее сразу передать данного значение соответствующей переменной типа: double Pt = Symbol_Properties::gd_Pt = 0; Но в таком случает компилятор ругается. Почему?

Scriptong: hoz пишет: В общем я сделал именно так: struct Symbol_Properties { static datetime gdt_Quote; // Время поступления последней котировки static double gda_Price [2]; // Текущие рыночные цены (0 - Bid, 1- Ask) static double gd_Spread; // Размер спреда в пунктах static double gd_Swap; // Своп static double gd_Comission; // Комиссия static double gd_Pt; // Величина одного пункта static int gi_Digits; // Количество знаков в цене после запятой static int gi_StopLevel; // Минимально-допустимый уровень стоп-лосса/тейк-профита в пунктах static int gi_FreezLevel; // Уровень заморозки ордеров в пунктах }; Описанное просто не имеет смысла. Об этом прямо говорит компилятор: struct has no members, size assigned to 1 byte - ни один из описанных членов структуры не воспринят, структура пустая Причина - указание членов структуры со спецификатором static. Это просто нонсенс, т. к. структура является типом данных, а не переменной. Статическими могут быть только переменные или члены класса, но не структур. hoz пишет: А гораздо удобнее сразу передать данного значение соответствующей переменной типа: double Pt = Symbol_Properties::gd_Pt = 0; Но в таком случает компилятор ругается. Почему? Замените на: double Pt = Symbol_Properties::gd_Pt; и все будет нормально с точки зрения синтаксиса. Хотя с точки зрения здравого смысла все очень плохо - зачем городить огород со структурами, если Вам проще использовать обычные локальные переменные?

hoz: Scriptong пишет: Причина - указание членов структуры со спецификатором static. Это просто нонсенс, т. к. структура является типом данных, а не переменной. Статическими могут быть только переменные или члены класса, но не структур. Это мне не понятно. Структура является типом данных ? Согласен. Но и класс тоже является типом данных. Так? Так! Получается, возникает вопрос, почему тогда у классах могут быть статические переменные, а у структур нет? Scriptong пишет: Хотя с точки зрения здравого смысла все очень плохо - зачем городить огород со структурами, если Вам проще использовать обычные локальные переменные? Если использовать просто переменные, то включая данный файл с переменными компилятор будет ругаться, что мол такие переменные "уже есть". Я это уже проходил. Т.е. при подгрузке каждого класса, например, с переменными: gdt_Expiration; gdt_OpenTime; gd_OpenPrice ; gd_Lots; gd_CurSL; gd_CurTP; gd_NewSL; gd_NewTP; gi_CurTicket; gi_Type; gi_Slippage; gi_Magic; gs_Comment; gs_Symbol; gu_Duration: Компилятор ругнётся, что каждый последующий раз когда будет подгружаться очередной класс( в который включён данный инклюдник к набором переменных ), что gdt_Expiration уже объявлен.. Раньше у меня такое было постоянно. Потому и пришлось прибегнуть к поиску другого варианта.

Scriptong: hoz пишет: Получается, возникает вопрос, почему тогда у классах могут быть статические переменные, а у структур нет? При всем сходстве структур и классов, у них есть множество различий. Одно из них - статические члены. hoz пишет: Компилятор ругнётся, что каждый последующий раз когда будет подгружаться очередной класс( в который включён данный инклюдник к набором переменных ), что gdt_Expiration уже объявлен.. Раньше у меня такое было постоянно. Потому и пришлось прибегнуть к поиску другого варианта. Тогда Вам нужно просто создать ОДИН-ЕДИНСТВЕННЫЙ включаемый файл, в котором описать необходимую структуру. И уже этот включаемый файл подключать ко всем своим проектам. Тогда и проблемы не будет. Вообще же создание единой "библиотеки" включаемых файлов - хорошая и удобная вещь. Посмотрите на мои проекты. Многие из них используют включаемые файлы: Common_Trade.mqh, Common_MathUtils.mqh, Common_GetSymbol.mqh. Эти файлы лежат в отдельной папке Common, которую я подключаю к новому проекту, если типы данных или функции, описанные в этих включаемых файлах, мне нужны.

hoz: Scriptong пишет: Тогда Вам нужно просто создать ОДИН-ЕДИНСТВЕННЫЙ включаемый файл, в котором описать необходимую структуру. И уже этот включаемый файл подключать ко всем своим проектам. Тогда и проблемы не будет. Я так и делаю. Но когда решил сделать члены статическими возникли проблемы. Scriptong пишет: Вообще же создание единой "библиотеки" включаемых файлов - хорошая и удобная вещь. Посмотрите на мои проекты. Многие из них используют включаемые файлы: Common_Trade.mqh, Common_MathUtils.mqh, Common_GetSymbol.mqh. Эти файлы лежат в отдельной папке Common, которую я подключаю к новому проекту, если типы данных или функции, описанные в этих включаемых файлах, мне нужны. Да, у Вас там серьёзный код. Нужно разбирать его. На это уйдёт некоторое время. Не так всё просто там.

Scriptong: hoz пишет: Но когда решил сделать члены статическими возникли проблемы. Предлагаю отталкиваться от простого факта - сделать статическими члены структуры не получится. Переделайте на класс, если уж так необходимо, хотя и не понимаю, зачем в данном случае это нужно.

hoz: Scriptong пишет: зачем в данном случае это нужно Почему? Как тогда нужно по Вашему? Scriptong пишет: Предлагаю отталкиваться от простого факта - сделать статическими члены структуры не получится. Как я понял, это всё недочёт мкл4. Вы и сами видели, что модератор на форуме метаквотов не смог ответить на вопрос. Да и в конце темы, которую я подымал там это всё-таки выяснилось. А что скажите по поводу статического объекта? class MyClass { }; static MyClass MyClassObj;

Scriptong: hoz пишет: А что скажите по поводу статического объекта? Ничего хорошего, т. к. в таком случае можно просто использовать обычные глобальные/локальные переменные в единственном экземпляре. Смысл использования статических типов данных в ООП заключается именно в том, чтобы иметь единое место хранения данных для всех объектов одного типа и при этом иметь гарантию невмешательства в эти данные со стороны других объектов. То есть речь идет именно о статических членах классов. Других практических примеров статических переменных я не вижу. Это больше подходит для академических изысков, к которым я, как практикующий программист, отношусь более чем прохладно.

hoz: Scriptong пишет: Это больше подходит для академических изысков Т.е. хотите сказать, что вариант предложенный модератором с форума метаквотов "не годным"? Имею ввиду для той задачи, которую я поставил. В плане инкапсуляции как я вижу это так. Но он по ходу этого так и не понял или просто мкл4 не позволяет это реализовать проще. Потому мало кто это умеет. То что у Вас это реализовано я видел. Но такой подход я осилю чутка позже Scriptong пишет: Это больше подходит для академических изысков, к которым я, как практикующий программист, отношусь более чем прохладно. Как же прохладно... У Вас же именно так и написан код... Весь инкапсулирован!

Scriptong: hoz пишет: Т.е. хотите сказать, что вариант предложенный модератором с форума метаквотов "не годным"? Какой именно вариант? Если Вы про объект, объявленный статически, то я по нему уже высказался. А насчет того, что кто-то там предложил такой вариант, нужно смотреть полный текст его предложения, чтобы ответить предметно. Ведь очень часто фразы попросту вырываются из контекста. hoz пишет: Имею ввиду для той задачи, которую я поставил. К сожалению, поставленные Вами цели для меня до сих пор остаются загадкой. Опишите свою задачу как можно подробнее, без абстракций, на конкретном примере. hoz пишет: Как же прохладно... У Вас же именно так и написан код... Весь инкапсулирован! Вот свежий пример вырывания фразы из контекста. Цитируемое Вами относится к рассуждениям о статическом объекте, а не о механизме инкапсуляции в целом.



полная версия страницы