我在嵌入式环境(Arduino/AVR ATMega328)中工作,并希望在 C++ 中实现工厂方法模式。但是,我使用的编译器 (avr-gcc) 不支持该new
关键字。有没有办法在不使用的情况下实现这种模式new
?
7 回答
由于 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
}
唯一要添加的是内存管理、内存块的分配和释放。这可以很简单地完成,注意不要破坏任何现有的分配内存(代码、静态/全局数据、堆栈)。您应该定义两个符号 - 一个用于空闲内存的开始,一个用于空闲内存的结束。您可以动态分配和释放该区域中的任何内存块。您将需要自己管理此内存。
如果没有办法在运行时实例化一个类,我想这是不可能的。您所能做的就是在编译时预先分配一些对象,创建对它们的引用并在需要时返回它们。
工厂方法的大图景是对象创建,这意味着堆内存消耗。在嵌入式系统上,您受到 RAM 的限制,需要在做出所有设计决策时考虑到内存限制。ATmega328 只有 2 KB RAM。我建议不要在如此狭小的空间内使用动态分配的内存。
在不更详细地了解您的问题的情况下,我建议静态声明该类的少数实例并以某种方式重用这些实例。这意味着您需要知道创建对象的时间和原因以及——同样重要的是——它们何时以及为什么结束;那么您需要弄清楚一次需要激活多少个以及一次可以激活多少个。
!!院长
这样的事情呢?
MyClass *objp = (MyClass*)malloc(sizeof(MyClass));
*objp = MyClass(); // or any other c'tor
编辑:忘了提,它假设 MyClass 有一个赋值运算符。
EDIT2:我忘记的另一件事 - 是的,有一个问题(它是 C++,总是有问题)。您必须为该对象手动调用 d'tor,因为您不能免费使用。
你可以做malloc吗?如果是这样,您可以这样 malloc 对象。
另外,您想从工厂创建的对象的性质是什么?
- 它们是不可变的吗?
- 工厂是否只打算生产一组在编译时可以知道的有限对象?
如果两个问题的答案都是肯定的,您可以为您的一组不可变对象静态分配内存,并让工厂方法返回指向适当对象的指针。
如果任何一个问题的答案都是否定的,这将不起作用。同样使用这种方法,您会遇到始终分配内存的问题。
如果您使用工厂意味着您想要一些动态绑定行为,这表明您有一些虚拟功能。虽然可以使用 malloc() 为对象分配内存,但类的 vtable 将无法正确设置,因此对虚函数的调用将崩溃。当需要动态绑定时,我看不到任何这样做的方法。
我在具有严格编码标准(不允许使用“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。