Я работаю во встроенной среде (Arduino/AVR ATMega328) и хочу реализовать шаблон Factory Method в C++. Однако компилятор, который я использую (avr-gcc), не поддерживает ключевое слово new
. Есть ли способ реализовать этот шаблон без использования new
?Могу ли я реализовать шаблон Factory Method в C++ без использования нового?
ответ
Поскольку компилятор AVR основан на компиляторе gcc, он, скорее всего, поддержит новое ключевое слово. Какова именно ошибка, которую вы получаете. Я предполагаю, что это ошибка ссылки/компилятора в строках неопределенной функции, а именно оператор new. Существует различие между новым оператором и оператором new, первый используется для создания объектов, а последний используется для выделения памяти для объектов. Новый оператор вызывает оператор new для типа создаваемого объекта, затем инициализирует v-таблицу объекта и вызывает конструкторы объекта. Reading this FAQ говорится, что оператор new не определен в стандартных библиотеках. Это легко исправить, просто определить одно:
void *operator new (size_t size)
{
return some allocated memory big enough to hold size bytes
}
и вам необходимо определить удаление, а также:
void operator delete (void *memory)
{
free the memory
}
Единственное, что нужно добавить, управление памятью, выделение и освобождение блоков памяти. Это можно сделать тривиально, стараясь не склеивать любую существующую выделенную память (код, статические/глобальные данные, стек).У вас должно быть два символа - один для начала свободной памяти и один для конца свободной памяти. Вы можете динамически выделять и освобождать любой фрагмент памяти в этом регионе. Вам нужно будет управлять этой памятью самостоятельно.
+1 - Я собираюсь объединить это с ответом Тэла и дать ему уйти. –
Можете ли вы сделать malloc? Если это так, вы можете malloc ваш объект таким образом.
Также какова природа ваших объектов, которые вы хотите создать с фабрики?
- Являются ли они неотразимыми?
- Является ли завод только предназначенным для создания ограниченного набора объектов, которые могут быть известны во время компиляции?
Если да, то вы можете статически распределить память для своего набора неизменяемых объектов и позволить фабричному методу возвращать указатели на соответствующий объект.
Это не сработает, если ответ не соответствует ни одному из вопросов. Также с этим подходом у вас есть проблема всегда иметь выделенную память.
Если не существует способа создать экземпляр класса во время выполнения, я полагаю, это невозможно. Все, что вы можете сделать, это предварительно выделить некоторые объекты во время компиляции, создать ссылки на них и вернуть их при необходимости.
Как насчет этого?
MyClass *objp = (MyClass*)malloc(sizeof(MyClass));
*objp = MyClass(); // or any other c'tor
EDIT: Забыл упомянуть, предполагается, что MyClass имеет оператор присваивания.
EDIT2: Еще одна вещь, которую я забыл - да, есть gotcha (это C++, всегда есть gotchas). Вам нужно будет вызвать дентер вручную для объекта, поскольку вы не можете использовать его бесплатно.
По крайней мере, он работает в VC++ 7. – sharptooth
Моя мать всегда предупреждала меня об использовании malloc() для создания экземпляра объекта C++. Даже если вы вызываете конструктор и копируете его данные в выделенную память, есть ли какие-либо проблемы с этим подходом? –
Да, есть очевидные ошибки: блок памяти не инициализирован, поэтому оператор присваивания должен реагировать соответственно - если он видит «инициализированный» указатель, он не должен пытаться освободить его, потому что он содержит мусор и висит. Я полагаю, что лучше всего вызвать calloc(), чтобы получить нулевой инициализированный блок памяти, чтобы этого избежать. – sharptooth
Если вы используете заводские средства, вы хотите, чтобы какое-то динамическое поведение привязки указывало на то, что у вас есть некоторые виртуальные функции. Хотя, возможно, будет возможно выделить память для объекта с помощью malloc(), таблица vtable класса будет неправильно настроена, и, следовательно, вызов виртуальных функций будет аварийно завершен. Я не вижу никакого способа сделать это, когда требуется динамическое связывание.
Это можно обойти - выделить объект в стеке и вызвать memcpy для указателя vtable, чтобы скопировать его на выделенный объект, выделенный в кучу. – sharptooth
Итак, вы говорите, что ответ Тэла (http://stackoverflow.com/questions/1031301/can-i-implement-the-factory-method-pattern-in-c-without-using-new/1031375#1031375) выиграл Работа? –
Я не пробовал. Но, по моему мнению, это не сработает. Однако обходной путь, предложенный sharptooth, может работать. – Naveen
Способ, которым я решил эту проблему во встроенной системе со строгими стандартами кодирования (где нам не разрешалось использовать «новое» или «удалить»), было создание статического массива желаемого объекта. А затем используйте статические указатели для уже выделенных объектов, сохраняя эти возвращаемые значения (используя статические переменные и/или переменные-члены) для последующего выполнения различных объектов.
// Class File ---------------------------------------------------
class MyObject {
public:
MyObject* getObject();
private:
const int MAX_POSSIBLE_COUNT_OF_OBJECTS = 10;
static MyObject allocatedObjects[MAX_POSSIBLE_COUNT_OF_OBJECTS];
static allocatedObjectIndex = 0;
};
// Implementation File ------------------------------------------
// Instantiate a static array of your objects.
static MyObject::allocatedObject[MAX_POSSIBLE_COUNT_OF_OBJECTS];
// Your method to return already created objects.
MyObject* MyObject::getObject() {
if (allocatedObjectIndex < (MAX_POSSIBLE_COUNT_OF_OBJECTS - 1)) {
return allocatedObjects[allocatedObjectIndex++];
} else {
// Log error if possible
return NULL;
}
}
Пожалуйста, предоставьте предупреждение. Это все из памяти, поскольку я не написал никаких C++ более чем за 8 месяцев.
Также обратите внимание: это имеет серьезный недостаток в том, что вы выделяете кучу ОЗУ во время компиляции.
Вы можете определить оператор MyObject :: new (size_t), который делает все вышеперечисленное, т. Е. Использует предварительно выделенный массив, сохраняя при этом знакомый новый синтаксис MyObject (args) вместо чего-то нестандартного. Таким образом, вы можете правильно построить и уничтожить объекты. – Skizz
Во встроенной системе я рассматриваю выделение группы RAN во время компиляции Good Thing, а не недостаток. –
Общая картина метода Factory - это создание объекта, что означает потребление памяти кучи. На встроенной системе вы ограничены оперативной памятью и должны принимать во внимание все ваши проектные решения с учетом ваших ограничений памяти. ATmega328 имеет только 2 КБ оперативной памяти. Я бы рекомендовал не использовать динамически выделенную память в таком ограниченном пространстве.
Не зная вашей проблемы более подробно, я бы рекомендовал статически объявить несколько экземпляров класса и повторно использовать эти экземпляры в некотором роде. Это означает, что вам нужно знать, когда и почему создаются ваши объекты, и - ТОЛЬКО КАК ВАЖНО - когда и почему они заканчиваются; то вам нужно выяснить, сколько вам нужно иметь активную за один раз и сколько из них можно активировать за один раз.
!! Dean
Все, потому что имеет 2 КБ или ОЗУ, не означает, что вы не можете выполнять динамическое распределение памяти. Вы просто не можете выделить столько. Вы можете получить 500 двухбайтовых объектов (500 * (2 для объекта + 2 для информации о размещении) = 2000). – Skizz
Skizz, ваши первые два предложения верны, но третий не является разумным. ОЗУ объемом 2 КБ (2048 байт) содержит как стек C, так и кучу; поэтому у него будет всего 48 байт для его стека C (необоснованно). Программа, которая нуждается в Factory Method, не является простой, поэтому его стек вызовов C будет меняться по глубине и может потенциально перезаписать объекты в куче. Динамическое распределение памяти возможно, но не безопасно в таком небольшом пуле памяти. Статическое распределение памяти будет легче управлять и, скорее всего, даст правильную программу. – dwhall
- 1. Могу ли я реализовать конструкцию Factory-pattern без использования new()?
- 2. Должен ли я использовать шаблон Factory Method?
- 3. Factory Method шаблон осветление
- 4. Factory Method шаблон с использованием Дженерики-C#
- 5. Factory Method шаблон против композиции
- 6. Могу ли я реализовать это как-то без использования нового ключевого слова? C++
- 7. C# generic factory method
- 8. Как я реализовать Factory шаблон без использования, если еще или переключатель случае весной с помощью аннотаций
- 9. Использование шаблона Factory Method в C++
- 10. реализовать шаблон запроса в коде C# без использования контекста данных
- 11. Абстрактные методы в «продукте» - Factory Method C#
- 12. Могу ли я реализовать одноэлементный шаблон?
- 13. Могу ли я использовать шаблон Factory в этом сценарии?
- 14. Внутренний класс Factory Method
- 15. Является ли шаблон Factory Method нарушением принципа Open/Closed?
- 16. Abstract Factory vs Factory Method (scope)
- 17. Abstract Factory, Factory Method, Builder
- 18. «Factory Method» Design Pattern
- 19. Factory Method - Неизвестные параметры
- 20. Как я могу реализовать действие «create» без «нового» действия
- 21. Singleton Factory method
- 22. Angularjs .factory method return
- 23. code factory method
- 24. Примеры реального мира шаблона Factory Method
- 25. Как я могу реализовать CursorLoader без использования Listview?
- 26. Decorator vs. abstract factory vs. factory method
- 27. Могу ли я создатьRecord() без использования save()?
- 28. Как преобразовать строку в кусок кода (Factory Method шаблон?)
- 29. Могу ли я написать приложение C без использования кучи?
- 30. Возможно ли реализовать шаблон «виртуального конструктора» на C# без приведения?
Как вы выделяете память? D: – GManNickG
Кроме того, поддерживает ли он размещение нового? Лучшее, что я могу придумать, - статически выделять кусок памяти, тогда вы можете разместить там что-то новое. – GManNickG
Память либо выделена в стеке (включая построение объекта на основе стека), либо с помощью malloc() - который не поддерживает конструкцию объекта. Размещение нового не поддерживается ни ... –