Есть такой код: Код (C++): struct Foo{ uint8_t a; uint8_t b; uint8_t c; }; Foo* getFoo(){ static Foo foo; if (foo.a != 1){ foo.a= 1; foo.b= 1; foo.c= 3; } return &foo; } void setup() { Serial.begin(9600); getFoo(); } void loop() { Foo* fp = getFoo(); fp->b++; Serial.println(fp->b); } Запустил, вроде как работает. считает от 0 до 255... У него есть какие нибудь подводные камни? или я параною?
foo это ненастоящая локальная переменная, она храница не в стеке, а в сегменте глобальных данных, как обычная глобальная переменная, патамуш надо хранить ее значение между вызовами. Единственное отличие от глобальной переменной, - область видимости, никто, кроме функции, ее содержащей, ее не видит. Ну а все, что храница в сегменте данных имеет постоянный адрес и если функция захочет им поделиться, кто ж ей посмеет отказать? Так что такая канструкция тоже имеет право на жизнь.
Например, сделать singleton. Код (C++): TObject *getObject() { static TObject *obj = NULL; if(obj==NULL) obj = new TObject(); return obj; }
чтобы сделать ее синглтоном и сныкать от неконтроллируемого использования. MyLib.h Код (C++): struct Foo{ uint8_t a; uint8_t b; uint8_t c; }; #ifndef API_DISABLED #define getFoo _getFoo() #define setFooA(_a) getFoo->a = (_a); #define setFooB(_b) getFoo->b = (_b); #define setFooC(_c) getFoo->c = (_c); #define doSomeAction(param) _doSomeAction(param) ; #else #define getFoo () (Foo*)NULL; #define setFooA(_a) #define setFooB(_b) #define setFooC(_c) #define doSomeAction(param) #endif MyLib.cpp Код (C++): #include <Arduino.h> #include "MyLib.h" Foo* _getFoo(){ static Foo foo; if(foo.a!=1){ foo.a=1; foo.b=1; foo.c=3; } return&foo; } void doSomeAction(char* param){ Serial.print(param); Serial.println(_getFoo()->a++); } mySketch.ino Код (C++): #include "MyLib.h" void setup() { Serial.begin(9600); setFooA(10); setFooB(12); setFooC(40); } void loop() { // some code _doSomeAction("Step1"); //some code _doSomeAction("Step2"); //.... } Если первой строкой скетча написать #define API_DISABLED то использование библиотеки выпилится из прошивки компилятором
Деда, это - НЕ синглтон. Потому как ничто мне не помешает сделать где-то в коде Код (C++): TObject* some = new TObject(); Синглтон - гарантирует единственность экземпляра. И делается через приватный конструктор и статический метод-член.
Не надо усложнять и придумывать какие-то гарантии и прочую чушь. При корректном использовании это работает как синлтон. А если кто-то захочет его сломать, то как ни пыжься — он это сделает. Хотя бы обратившись к конструктору прямо по адресу.
Это не чушь, а определение синглтона. Усложнение тут не при чём - приведённый выше подход имеет место быть и право на жизнь, просто не надо называть это синглтоном, вот и всё.
Спасибо за самое правильное определение, самый умный человек. Что бы человечество делало без вас? Все друг друга поняли и разошлись? Так нельзя. Никто же не стал потрясающе умнее и лучше во всех отношениях благодаря вашему неприкасаемому единственно верному определению синглтона.
Так и я без претензий. Я не боюсь признавать, что неправ, а та хрень, что я написал в 5 утра по нашему, действительно синглтоном не является. ПризнаЮ. С++ пока для меня как польский после русского, вроде чтото понятно, а сиравно плаваю.
Тады слушай, позанудствую, пока дядя Витя недремлющее око отвернул в другую сторону: синглтон к С++ не имеет никакого отношения - это просто паттерн проектирования, реализуется на любом языке, даже челочечьем. Это, строго говоря, инструмент, со своими характерными для инструмента признаками. В рамках профессии, считаю, должна быть определённая грамотность; для меня программирование - профессия, вот и заметил, без всяких претензий и прочего. Занудство окончено З.Ы. Сейчас придёт дядя Витя и скажет, что похер как микроскоп называть - всё равно все всё поняли и им можно гвозди забивать