7

我在嵌入式环境(Arduino/AVR ATMega328)中工作,并希望在 C++ 中实现工厂方法模式。但是,我使用的编译器 (avr-gcc) 不支持该new关键字。有没有办法在不使用的情况下实现这种模式new

4

7 回答 7

8

由于 AVR 编译器是基于 gcc 编译器的,因此很有可能支持 new 关键字。你得到的错误到底是什么。我猜这是一个未定义函数的链接/编译器错误,即 operator new。new操作符和new操作符是有区别的,前者用于创建对象,后者用于为对象分配内存。new 运算符为正在创建的对象类型调用 operator new,然后初始化对象的 v-table 并调用对象的构造函数。阅读这个常见问题解答它说标准库中没有定义 operator 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
}

唯一要添加的是内存管理、内存块的分配和释放。这可以很简单地完成,注意不要破坏任何现有的分配内存(代码、静态/全局数据、堆栈)。您应该定义两个符号 - 一个用于空闲内存的开始,一个用于空闲内存的结束。您可以动态分配和释放该区域中的任何内存块。您将需要自己管理此内存。

于 2009-06-23T10:07:35.697 回答
3

如果没有办法在运行时实例化一个类,我想这是不可能的。您所能做的就是在编译时预先分配一些对象,创建对它们的引用并在需要时返回它们。

于 2009-06-23T08:34:33.560 回答
3

工厂方法的大图景是对象创建,这意味着堆内存消耗。在嵌入式系统上,您受到 RAM 的限制,需要在做出所有设计决策时考虑到内存限制。ATmega328 只有 2 KB RAM。我建议不要在如此狭小的空间内使用动态分配的内存。

在不更详细地了解您的问题的情况下,我建议静态声明该类的少数实例并以某种方式重用这些实例。这意味着您需要知道创建对象的时间和原因以及——同样重要的是——它们何时以及为什么结束;那么您需要弄清楚一次需要激活多少个以及一次可以激活多少个。

!!院长

于 2009-06-24T17:35:32.507 回答
1

这样的事情呢?

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

编辑:忘了提,它假设 MyClass 有一个赋值运算符。

EDIT2:我忘记的另一件事 - 是的,有一个问题(它是 C++,总是有问题)。您必须为该对象手动调用 d'tor,因为您不能免费使用。

于 2009-06-23T08:41:43.937 回答
0

你可以做malloc吗?如果是这样,您可以这样 malloc 对象。

另外,您想从工厂创建的对象的性质是什么?

  • 它们是不可变的吗?
  • 工厂是否只打算生产一组在编译时可以知道的有限对象?

如果两个问题的答案都是肯定的,您可以为您的一组不可变对象静态分配内存,并让工厂方法返回指向适当对象的指针。

如果任何一个问题的答案都是否定的,这将不起作用。同样使用这种方法,您会遇到始终分配内存的问题。

于 2009-06-23T08:30:34.567 回答
0

如果您使用工厂意味着您想要一些动态绑定行为,这表明您有一些虚拟功能。虽然可以使用 malloc() 为对象分配内存,但类的 vtable 将无法正确设置,因此对虚函数的调用将崩溃。当需要动态绑定时,我看不到任何这样做的方法。

于 2009-06-23T08:52:17.160 回答
0

我在具有严格编码标准(不允许使用“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;
    }
}

请预先警告。这一切都来自记忆,因为我已经超过 8 个月没有写过任何 C++ 了。

另请注意:这有一个严重的缺点,因为您在编译时分配了一堆 RAM。

于 2009-06-23T21:36:15.610 回答