dxp 68 12 декабря, 2011 Опубликовано 12 декабря, 2011 · Жалоба new нету, дорого new можно свой написать, будет недорого. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrewlekar 0 12 декабря, 2011 Опубликовано 12 декабря, 2011 · Жалоба Ну если забить на наследование, абстракцию и прочую фигню, то можно вот так реализовать: class Base{ public: Base(void **array) { _a=array; } void *getItem(int n){ return _a[n]; } private: void **_a; }; class Derived: public Base{ public: Derived(void **array, int z) : Base(array){other = z;} private: int other; }; Derived derived1(0, 0); Derived derived2(0, 1); Derived derived3(0, 2); void *array[]={&derived1, &derived2, &derived3}; //Derived aaa[]={Derived(0, 0),Derived(0, 1),Derived(0, 2)}; void main() { Derived d3((void **)array, 3); Derived *x = (Derived *)d3.getItem(2); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 12 декабря, 2011 Опубликовано 12 декабря, 2011 · Жалоба Он в принципе написан, почти, только на даной платформе и так вся память забита статикой- много данных...(причем используется почти вся, ну мож 2-4кб в резерве и в редкоиспользуемых переменных из 64), места под кучу нету. я кучи юзаю только если есть внешняя sram Ну если забить на наследование, абстракцию и прочую фигню, то можно вот так реализовать: ну у меня примерно так и реализовано, только с наследованием, абстракцией,... :) цель - упростить создание обьектов, тк их много, где-то тупанешь, в массив не туда указатель всунешь и потом сложно найти ошибку... Гораздо проще, когда в ините массива сразу конструктор видно, те. видно,что за обьект туда впихнули... Пока создаю каждый под своим именем, хоть какая-то визуализация есть... типа так .... static MenuItemInt<U8> miContrast(0,"Contrast:",&g_mainsetup.contrast,1,100); static MenuItemInt<U8> miBright(0,"Bright:",&g_mainsetup.brightness,0,100); static MenuItemInt<U8> miLedTime(0,"LED time:",&g_mainsetup.lighto,5,255); static MenuItemInt<U8> miKbdVol(0,"KBD vol:",&g_mainsetup.kbdsndvol,0,128); ... static MenuItem* const settingsItemsList[]={ &miContrast,&miBright,&miLedTime,&miKbdVol,... }; ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 12 декабря, 2011 Опубликовано 12 декабря, 2011 · Жалоба немного офф (без холивара): Че ж вы почте все так упорно адреса объектов передаете через указатели ?! Чай не на С пишете, а С с плюсами. В С++ для этого придумана передача по ссылке - удобнее и безопаснее. Да и код становится чище и более читаем. К тому же существует такая чудесная вещь - перегрузка стандарных операторов: = + - << >> &* и т.д. Оч. сильно сокращает текст кода. Кто-нить пользуется? Тем более без "наследования, абстракции и прочей фигни", ну, уже никак нельзя. Иначе это возврат в каменный век - чистый С. .... static MenuItemInt<U8> miContrast(0,"Contrast:",&g_mainsetup.contrast,1,100); static MenuItemInt<U8> miBright(0,"Bright:",&g_mainsetup.brightness,0,100); static MenuItemInt<U8> miLedTime(0,"LED time:",&g_mainsetup.lighto,5,255); static MenuItemInt<U8> miKbdVol(0,"KBD vol:",&g_mainsetup.kbdsndvol,0,128); ... static MenuItem* const settingsItemsList[]={ &miContrast,&miBright,&miLedTime,&miKbdVol,... }; ... В догонку у меня к brag (и к остальным) несколько вопросов: Как вы определяет порядок создания объектов (вызовы конструкторов) при таком статическом размещении? Понятно, что в пределах одного С++ файла объекты скорее всего будут создаваться в порядке размещения в коде. А как быть, если таких файлов более одного? И как быть, если объекты должны создаваться в определенном порядке, а надежды на разум линкера мало? Вот пример такой ситуации: Один объект - драйвер ЖК экрана (монитора), а другой - некий видгет. Видгет прямо в конструкторе хочет нарисоваться на экране. Это возможно, если сначала в С++ файле будет объявлен драйвер, а потом видгет. Это сработает всегда, т.к. это видно визуально прямо в тексте кода, наглядно. А что делать, если видгетов - оч. много, многие являются полями других объектов и размещены в других файлах? Где гарантия, что линкер в сначала засунет в список вызова перед main конструктор драйвера экрана, а потом всего остального? Ну, ясно, что есть такая штука, как отложенная инициализация. Но это раздувает код. Есть идеи? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 12 декабря, 2011 Опубликовано 12 декабря, 2011 · Жалоба Массив ссылок в C++ создать нельзя. Перегрузкой пользуемся конечно, только как ее сюда втулить -хз, похоже таки никак Как вы определяет порядок создания объектов (вызовы конструкторов) при таком статическом размещении? Поа никак, но смотрел init_array - тулит в нужном порядке. Понятно, что в пределах одного С++ файла объекты скорее всего будут создаваться в порядке размещения в коде. ну да. Этот код предназначен для компиляции в одном файле, потому везде ключевые слова "static". Далее после создания массива идет создание обьекта, которые его использует, типа static Menu settingsMenu(Rect(0,8,96,56),0,settingsItemsList,sizeof(settingsItemsList)/sizeof(MenuItem*)); Вся эта муть создается в одном файле, а уже реализация классов в других И как быть, если объекты должны создаваться в определенном порядке, а надежды на разум линкера мало? Если есть хоть какая-то зависимость от порядка - я делаю либо отдельный метод init() в классах либо создается обьявляется пустышка в статике, а затем присваивается уже в коде нужное значение: BragClassebta c1; ... somecoolfunction(){ c1=BragClassebta(hlam_usjakij,...); } Видгет прямо в конструкторе хочет нарисоваться на экране. Лично у меня в конструкторах рисовалок нету, рисавалки далеко в недрах всяких message-loop. Ну, ясно, что есть такая штука, как отложенная инициализация. Но это раздувает код. Есть идеи? С данной темой стыкаюсь постоянно, в ОС разные обьекты должны создаватся в разное определенное время, потому юзаю всякие отложенные действия... но по моему единохренственно, что в коде будет что-то типа MyFuckingClass *a; ... Someclass::somefunction(){ a=new MyFuckingClass(); } Что MyFuckingClass a; ... Someclass::somefunction(){ a.init(); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 12 декабря, 2011 Опубликовано 12 декабря, 2011 · Жалоба Вот пример такой ситуации: Один объект - драйвер ЖК экрана (монитора), а другой - некий видгет. Видгет прямо в конструкторе хочет нарисоваться на экране. Делаем у драйвера статическую функцию-член: static Driver& Instanse() { static Driver instance; return instance; } И все, кто хочет отрисоваться на экране, обращаются к драйверу через неё: Vidget::Draw() { Driver& drv = Driver::Instanse(); drv.Draw(this); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 12 декабря, 2011 Опубликовано 12 декабря, 2011 · Жалоба И все, кто хочет отрисоваться на экране, обращаются к драйверу через неё: Ага, только мютекс для static Driver instance; кто будет создавать, лочить,... и когда? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 12 декабря, 2011 Опубликовано 12 декабря, 2011 · Жалоба И все, кто хочет отрисоваться на экране, обращаются к драйверу через неё: Vidget::Draw() { Driver& drv = Driver::Instanse(); drv.Draw(this); } Наверно, я предложил не очень наглядный пример для этого случая... По сути то, что вы предлагаете - класс-синглтон. В нем можно тогда уже все функции сделать статическими )) Да, я согласен, это идеальный вариант для единственного экрана, порта или какой-нить периферии и т.п. А как быть, если их больше одного? Сам отвечу - разные классы драйверов, наследованные от одного абстрактного класса драйвера с парой-тройкой чисто виртуальных функций, которые определяют разницу между разными драйверами. Короче, вот другой пример: есть некий протокол обмена к которому привязан свой драйвер, нужно совместное проживаение более одного такого протокола в прелах одного кода протоколы абсолютно одинаковые (пусть это будут два TCP/IP каждый на своем ETH) экзэмпляр одного протокола находится в одном файле, другой - в другом файле, объявлены через static их нужно запускать в определеном порядке, синхронизировать, Как это сделать без глобальных объектов? Ага, только мютекс для static Driver instance; кто будет создавать, лочить,... и когда? В принципе, лочить можно внутри каждого метода отрисовки. Я так однажды делал. Мьютекс лежит среди полей класса драйвера, инитится в initialize() методе драйвера. Массив ссылок в C++ создать нельзя. А это сделано намеренно :) Ссылку можно дать на экзэмпляр класса, который владеет этим массивом и т.о. защить его от прямых попыток изменения соотв. методами. Так код делается значительнее безопаснее. Перегрузкой пользуемся конечно, только как ее сюда втулить -хз, похоже таки никак Я ж предупредил - немного офф )) А перегрузку можно вообще всунуть куда угодно )) Но подобный фанатизм до добра не доведет... Поа никак, но смотрел init_array - тулит в нужном порядке. Прощу прощения за мое невежество, а что это такое? static Menu settingsMenu(Rect(0,8,96,56),0,settingsItemsList,sizeof(settingsItemsList)/sizeof(MenuItem*)); Вся эта муть создается в одном файле, а уже реализация классов в других Вот именно и выходит муть - ее не разобрать без "словаря" уже через месяц отдыха )) Куча параметров в одной строчке. Куча static объектов. А так как их конструторы с параметрами, то их уже не засунуть никуда, кроме как в начало С++ файла (это я про читаемость кода). С развитием проекта наступит точка хаоса... )) А как вы ссылаетесь на них из других объектов, объявленных в других файлах? Если есть хоть какая-то зависимость от порядка - я делаю либо отдельный метод init() в классах либо создается обьявляется пустышка в статике, а затем присваивается уже в коде нужное значение: Ну вот так и рождаются "костыли". Неправильно это как-то. Пока код маленький - все гуд, но потом приходит жопа. Ну, должно ж быть "резиновое" решение, которое будет работать на коде любой сложности и объема. но по моему единохренственно, что в коде будет что-то типа MyFuckingClass *a; ... Someclass::somefunction(){ a=new MyFuckingClass(); } Что MyFuckingClass a; ... Someclass::somefunction(){ a.init(); } Согласен, одно и то же, но классическая хуча в эмбэддед софтах - величайшее зло :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 13 декабря, 2011 Опубликовано 13 декабря, 2011 · Жалоба Как это сделать без глобальных объектов? Легко. Через интерфейсы. А выбор интерфейса где-то предусмотреть. А экземпляр обьекта TCP создавать непосредственно перед использованием, к стати и тут может происходить выбор интерфейса. Код выглядит всегда одинаково и никакой связи между файлами драйвера и файлами протокола нету. class IPaintEngine{ public: virtual int w()=0; virtual int h()=0; virtual void drawText(const Point &pos,const char *text,const Palette &pal)=0; virtual void drawRect(const Rect &rect,const Palette &pal)=0; }; Сама рисовалка. Пусть это будет наш протокол. Экземпляр создается тогда,когда он нам нужен: class Painter{ public: Painter(PaintDevice *dev); void drawText(const Point &pos,const char *text,const Palette &pal); void drawRect(const Rect &rect,const Palette &pal); void fillBackground(const Palette &pal); ... private: PaintDevice *paintdev; ... }; От этого наследуемся, если хотим уметь рисовать: class PaintDevice{ public: virtual IPaintEngine* paintEngine()=0; ... }; И организовываем выбор драйвера через virtual IPaintEngine* paintEngine(); Рисуем class Widget : public PaintDevice{ public: ... virtual void draw(){ Painter painter(this); painter.drawText(Point(0,0),"Hello word"); } ... }; Наверное заметили некое сходство с Qt... :) Да, некоторые идеи я передрал с докуминтации Qt ;) В принципе, лочить можно внутри каждого метода отрисовки. Я так однажды делал. Мьютекс лежит среди полей класса драйвера, инитится в initialize() методе драйвера. Нет, вы немного не поняли. Кто лочить будет static Driver instance; ? Ведь вызватся функция static Driver& Instanse() может одновременно, когда обьект instance еще не создан. Один тред вызвал Instanse(), та запустила конструктор для instance (тк instance еще не создан) и тут процесс посреди конструктора прервался и кто-то другой опять вызвал Instanse() и ...и сами понимаете что :) Ведь процесс создания instance мы никак не контроллируем... Я синглтоны делаю так: class BragUI{ public: BragUI(); static BragUI& getInst()const{ return ui; } private: static BragUI ui; }; .... BragUI::ui=BragUI(); Прощу прощения за мое невежество, а что это такое? Это такая хреновина... Регламентировано ARM IHI0041C CPPABI: Each element of the vector contains the address of a function of type extern “C” void (* const)(void) that, when called, performs part or all of the global object construction for the translation unit. Нам остается их вызвать где-то при старте for(i=0;i<sizeofinitarray;i++)__init_array(); Вот именно и выходит муть - ее не разобрать без "словаря" уже через месяц отдыха )) Куча параметров в одной строчке. Куча static объектов. А так как их конструторы с параметрами, то их уже не засунуть никуда, кроме как в начало С++ файла (это я про читаемость кода). С развитием проекта наступит точка хаоса... )) Это процесс создания окошек. А реализация уже в других файлах. в будущем вообще этот код будет софтиной-дизайнером генерится( типа как в Qt :) ). В файле с этой кучей статиков больше ничего нету. Согласитесь, создание графических обьектов где-попало в коде в разных файлах приведет к еще хужему хаоссу :) Ну всякие там MessageBox-ы и диалоги ессно создаются в стеке когда это нужно, эти массивы надо только для построения основного ui. А как вы ссылаетесь на них из других объектов, объявленных в других файлах? Зачем на них ссылаться? Досточно выполнить execMenu(); где нам нужно static Menu mainMenu(Rect(0,8,96,56),0,mainItemsList,sizeof(mainItemsList)/sizeof(MenuItem*)); void execMenu(){ mainMenu.exec(); } Ну вот так и рождаются "костыли". Неправильно это как-то. Пока код маленький - все гуд, но потом приходит жопа. Ну, должно ж быть "резиновое" решение, которое будет работать на коде любой сложности и объема. Поможет разве что раздельная линковка ОС и программы с тредами. Сначала стартует ОС, подготавливает почву для создания всяких мютексов, а потом стартует прога и уже спокойно можно реализовывать такие синглтоны: class Single{ public: Single(){ initialized=0; } static Single& getInst(){ inst.m.lock(); if(!inst.initialized)inst.init(); inst.m.unlock(); return inst; } private: static Single inst; Mutex m; bool initialized; void init(); }; Single Single::inst=Single(); Согласен, одно и то же, но классическая хуча в эмбэддед софтах - величайшее зло Ну да, потому я за init() :) Не так их уж и много этих синглтонов (у меня только они требуют init() ). Это обычно всякие драйвера там. Да и можно этот init как-то назвать,чтобы заметен был и софтину сделать, которая код прочесывает и выдает ошиибку, если эта ф-я не вызвана :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 68 13 декабря, 2011 Опубликовано 13 декабря, 2011 · Жалоба К тому же существует такая чудесная вещь - перегрузка стандарных операторов: = + - << >> &* и т.д. Оч. сильно сокращает текст кода. Кто-нить пользуется? А как же. :) Регулярно. Но без фанатизма. Там, где уместно. Например, при работе с координатами экране есть класс TPoint, который предоставляет всю арифметику вычисления координат. Получается удобнее и читабельнее, нежели функции вызывать. В догонку у меня к brag (и к остальным) несколько вопросов: Как вы определяет порядок создания объектов (вызовы конструкторов) при таком статическом размещении? Понятно, что в пределах одного С++ файла объекты скорее всего будут создаваться в порядке размещения в коде. А как быть, если таких файлов более одного? И как быть, если объекты должны создаваться в определенном порядке, а надежды на разум линкера мало? Ну, штатное решение - singleton. Но он вас почему-то не устраивает. А, тем не менее, работает предсказуемо, надёжно и эффективно. Пользуемся. ну да. Этот код предназначен для компиляции в одном файле, потому везде ключевые слова "static". Не понимаю, почему вы упорно проводите в жизнь икапсуляцию на уровне единиц трансляции, а не на основе классов, кои есть штатное средство языка для этого? Ведь если бы классами не пользовались, было бы понятно. В С такой подход тоже понятен. Но не в С++. Короче, вот другой пример: есть некий протокол обмена к которому привязан свой драйвер, нужно совместное проживаение более одного такого протокола в прелах одного кода протоколы абсолютно одинаковые (пусть это будут два TCP/IP каждый на своем ETH) экзэмпляр одного протокола находится в одном файле, другой - в другом файле, объявлены через static их нужно запускать в определеном порядке, синхронизировать, Как это сделать без глобальных объектов? Что-то всё равно не понятно, что вы хотите сделать. :cranky: Ну вот так и рождаются "костыли". Неправильно это как-то. Пока код маленький - все гуд, но потом приходит жопа. Ну, должно ж быть "резиновое" решение, которое будет работать на коде любой сложности и объема. Кстати, фреймворк Qt идёт по совсем простому пути - там до старта main(), а точнее, до создания объекта QAppication никакие GUI'ные объекты не рожаются - это запрещено идеологически. Поэтому с порядком создания объектов проблем нет. Очень простой и эффективный способ. Правда, для embedded в том виде, как это там реализовано, это не годицца - там всё это живёт на new. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 13 декабря, 2011 Опубликовано 13 декабря, 2011 · Жалоба Не понимаю, почему вы упорно проводите в жизнь икапсуляцию на уровне единиц трансляции, а не на основе классов, кои есть штатное средство языка для этого? Ведь если бы классами не пользовались, было бы понятно. В С такой подход тоже понятен. Но не в С++. А как в данном случаи быть иначе? Ну, штатное решение - singleton. Но он вас почему-то не устраивает. А, тем не менее, работает предсказуемо, надёжно и эффективно. Пользуемся. выше я писал почему не конает... "Нет, вы немного не поняли. Кто лочить будет static Driver instance; ?....." я еще буду думать, возможно удстся сделать что-то такое, чтобы можно было создавать мютексы в static, тогда см. реализацию синглтона выше Кстати, фреймворк Qt идёт по совсем простому пути - там до старта main(), а точнее, до создания объекта QAppication никакие GUI'ные объекты не рожаются - это запрещено идеологически. Поэтому с порядком создания объектов проблем нет. Очень простой и эффективный способ. Правда, для embedded в том виде, как это там реализовано, это не годицца - там всё это живёт на new. Моя реализация выше идеологически примерно такая же, только по проще и без new. conncet прикольная штука у них, сокращает число строк кода, но для embedded не годится. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 68 13 декабря, 2011 Опубликовано 13 декабря, 2011 · Жалоба Я синглтоны делаю так: class BragUI{ public: BragUI(); static BragUI& getInst()const{ return ui; } private: static BragUI ui; }; .... BragUI::ui=BragUI(); А зачем так сложно и неуниверсально? Почему не сделать так: template<typename T> class singleton { public: static T& instance() { static T Instance; return Instance; } }; ? Тут не нужно руками размещать внутреннюю переменную и нет привязки к конкретному типу - синглтон создаётся под конкретный тип компилятором. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 13 декабря, 2011 Опубликовано 13 декабря, 2011 · Жалоба А зачем так сложно и неуниверсально? Почему не сделать так: Уже писал, одновременный вызов static T& instance() { static T Instance; даст гонки! вернее захочет это предотвратить и попытается вызвать __cxa_guard_acquire, которая должна в свою очередь обработать это дело (это что касается gcc). если даже мы ее реализуем, то мютекс не всегда можно создавать, вдруг мы instance() вызовем до того, как можно создавать мютексы? или еще хуже - вызовем из прерывания, где вообще запрещены всякие блокировки и синхронизация там происходит совсем по другим принцыпам? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 68 13 декабря, 2011 Опубликовано 13 декабря, 2011 · Жалоба А как в данном случаи быть иначе? Я что-то туплю, не понимаю, что тут дают статики. выше я писал почему не конает... "Нет, вы немного не поняли. Кто лочить будет static Driver instance; ?....." я еще буду думать, возможно удстся сделать что-то такое, чтобы можно было создавать мютексы в static, тогда см. реализацию синглтона выше Ну, так завернуть драйвер и мутекс в один класс, через который и работать. Но я делаю не так: завожу очередь сообщений, и все, кто обращается к экрану, мечут сообщения в очередь, которую разгребает с другого конца уже ответственный за это код. Такой подход рулит тем, что не тормозит ни один процесс в случае, когда ресурс занят - в случае с мутексом будет ожидание, а тут нет - просто метнул сообщение в очередь и занимается дальше своими делами. Такой подход подробно описан тут в приложении А (Очередь заданий). Уже писал, одновременный вызов static T& instance() { static T Instance; даст гонки! Если это так важно, то можно использовать критическую секцию, она оверхеда почти не добавит и динамику не ухудшит. вернее захочет это предотвратить и попытается вызвать __cxa_guard_acquire, которая должна в свою очередь обработать это дело (это что касается gcc). если даже мы ее реализуем, то мютекс не всегда можно создавать, вдруг мы instance() вызовем до того, как можно создавать мютексы? или еще хуже - вызовем из прерывания, где вообще запрещены всякие блокировки и синхронизация там происходит совсем по другим принцыпам? Я не понимаю, причём тут мутексы? Для защиты синглтона? Так тут мутексы слишком тяжелы и избыточны - враппер критической секции в этом случае рулит безальтернативно. Возможно, вы имеет в виду какие-то нюансы своего проекта, которые мне неизвестны. Но я и не про конкретный проект говорю, а про синглтоны в общем случае. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 13 декабря, 2011 Опубликовано 13 декабря, 2011 · Жалоба Спасибо У мена какраз на lock-free очередях реализована синхронизация в прерываниях и внутри сис.вызовов. Локов там нет. в самом приложении уже где как. Если это какой-то томозный девайс, типа gsm-модема, то очередь там может быстро переполнится без локов. Если это так важно, то можно использовать критическую секцию, она оверхеда почти не добавит и динамику не ухудшит. Критическая секция, в смысле запрет прерываний? ессли да, то в моем случаи,на пример, этого делать нельзя. прерывания разрешены всегда, еще где-то с начала старта ОС. а то этим термином много чего называют... Я не понимаю, причём тут мутексы? Для защиты синглтона? да Так тут мутексы слишком тяжелы и избыточны Ну у меня они довольно легкие __cxa_guard тоже документированы в arm cppabi 3.2.3.2 One-time construction API extern "C" int __cxa_guard_acquire(int *guard_object); If the guarded object has not yet been initialized, this function returns 1. Otherwise it returns 0. If it returns 1, a semaphore might have been claimed and associated with guard_object, and either __cxa_guard_release or __cxa_guard_abort must be called with the same argument to release the semaphore. extern "C" void __cxa_guard_release(int *guard_object); еще будем думать над этим... к тому же я MPU использую, там все еще хуже... Я что-то туплю, не понимаю, что тут дают статики. Просто чтобы прятать с глаз всякую муть. в Qt это реализовано аналогично - генерится отдельный ui_ххх.h файл, где есть функция создания всех обьектов интерфейса, запихнуто в namespace. У меня это тоже отдельный файл, только у меня все построено на статической памяти, а у них на new Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться