Могу ли я реализовать шаблон заводского метода на C ++ без использования new?

StackOverflow https://stackoverflow.com/questions/1031301

Вопрос

Я работаю во встроенной среде (Arduino / AVR ATmega328) и хочу реализовать шаблон заводского метода на C ++.Однако компилятор, который я использую (avr-gcc), не поддерживает new ключевое слово.Есть ли способ реализовать этот шаблон без использования new?

Это было полезно?

Решение

Поскольку компилятор AVR основан на компиляторе gcc, он, скорее всего, будет поддерживать новое ключевое слово. Какую именно ошибку вы получаете. Я предполагаю, что это ошибка ссылки / компилятора вдоль строк неопределенной функции, а именно, оператора new. Существует разница между оператором new и оператором new: первый используется для создания объектов, а второй - для выделения памяти для объектов. Оператор new вызывает оператор new для типа создаваемого объекта, затем инициализирует v-таблицу объекта и вызывает конструкторы объекта. Читая этот 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
}

Единственное, что нужно добавить - это управление памятью, выделение и освобождение блоков памяти. Это можно сделать тривиально, следя за тем, чтобы не затереть существующую выделенную память (код, статические / глобальные данные, стек) У вас должно быть определено два символа - один для начала свободной памяти и один для конца свободной памяти. Вы можете динамически распределять и освобождать любой фрагмент памяти в этом регионе. Вам нужно будет самостоятельно управлять этой памятью.

Другие советы

Если нет способа создать экземпляр класса во время выполнения, я полагаю, это невозможно. Все, что вы можете сделать, - это предварительно выделить некоторые объекты во время компиляции, создать ссылки на них и вернуть их при необходимости.

Общая картина Фабричного метода - это создание объекта, что означает потребление кучи памяти.Во встраиваемой системе вы ограничены объемом оперативной памяти и должны принимать все свои проектные решения с учетом ограничений памяти.ATmega328 имеет всего 2 КБ оперативной памяти.Я бы не рекомендовал использовать динамически выделяемую память в таком ограниченном пространстве.

Не зная вашу проблему более подробно, я бы рекомендовал статически объявить несколько экземпляров класса и повторно использовать эти экземпляры тем или иным способом.Это означает, что вам нужно знать, когда и почему создаются ваши объекты и - ЧТО НЕ МЕНЕЕ ВАЖНО - когда и почему они заканчиваются;затем вам нужно выяснить, сколько человек вам нужно иметь активными одновременно и сколько их возможно иметь активными одновременно.

!!Декан

Как насчет этого?

MyClass *objp = (MyClass*)malloc(sizeof(MyClass));
*objp = MyClass();  // or any other c'tor

РЕДАКТИРОВАТЬ: забыл упомянуть, предполагается, что MyClass имеет оператор присваивания.

РЕДАКТИРОВАТЬ2: Еще одна вещь, которую я забыл - да, есть ошибки (это C ++, всегда есть ошибки). Вам придется вызывать d'tor вручную для объекта, так как вы не можете использовать free.

Если вы используете фабрику, это означает, что вам нужно динамическое связывание, которое указывает на наличие некоторых виртуальных функций. Хотя может быть возможно выделить память для объекта с помощью malloc (), виртуальная таблица класса не будет настроена должным образом, и, следовательно, вызов виртуальных функций завершится сбоем. Я не вижу способа сделать это, когда требуется динамическое связывание.

Ты можешь сделать malloc?Если это так, вы можете таким образом заблокировать свой объект.

Кроме того, какова природа ваших объектов, которые вы хотите создать на Заводе?

  • Поддаются ли они имитации?
  • Предназначена ли фабрика только для создания ограниченного набора объектов, которые могут быть известны во время компиляции?

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

Это не сработает, если ответ будет отрицательным ни на один из вопросов.Кроме того, при таком подходе у вас возникает проблема с постоянным выделением этой памяти.

Я решил эту проблему во встроенной системе со строгими стандартами кодирования (где нам не разрешалось использовать «new» или «delete») - создать статический массив нужного объекта. А затем используйте статические указатели на уже выделенные объекты, сохраняя эти возвращаемые значения (используя статические переменные и / или переменные-члены) для последующего выполнения различных объектов.

// 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 месяцев.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top