有没有办法防止类的动态分配?

7
我在我的嵌入式系统中使用C++基类和子类(为了清晰起见,我们称它们为A和B)。由于时间和空间的紧迫性,我需要使其尽可能地简洁。编译器抱怨缺少虚析构函数,我理解这一点,因为如果您分配了一个B*,然后将指针作为A*实例删除,则可能会遇到问题。但是,我永远不会分配任何此类类的实例。有没有一种方法可以重载operator new(),以便如果没有对任何类进行动态分配,则会编译,但如果最终用户尝试分配新的A或B实例,则会导致编译器错误?我正在寻找一种类似于通过私有构造函数“毒化”自动编译器复制构造函数的常见技术的方法。 (例如http://channel9.msdn.com/Forums/TechOff/252214-Private-copy-constructor-and-private-operator-C

你帖子的最后一部分让我想知道是否你需要一个Singleton模式的实现。http://en.wikipedia.org/wiki/Singleton_pattern - Rycul
@Rycul:谢谢,它们不是单例,只是在小型嵌入式系统中,我们倾向于使用静态或堆栈分配来完成几乎所有操作。 - Jason S
只是出于好奇。我不明白,为什么你需要一个虚析构函数呢?仅仅因为你正在派生并不意味着你需要一个虚析构函数。你有其他的虚函数吗?如果你一开始就不使用动态内存,那么你将如何使用这样的函数呢? - alfC
@JasonS,是的,但我猜编译器抱怨是因为你已经有至少一个虚函数了。不是吗?然后我的问题是,如果你从来没有打算对对象进行多态操作,为什么一开始就要有虚函数呢? - alfC
我不知道,那是8年前的事了...但我认为我没有使用任何虚函数。<strike>当时用的是MS Visual C++,不确定是哪个版本,但可能是MSVC 2005</strike>对了,那是一个嵌入式系统。那么应该是TI的C2000编译器。而且,我没有使用虚函数。 - Jason S
显示剩余2条评论
3个回答

9

您可以像毒害复制构造函数一样毒害operator new。只需确保不要毒害放置new。虚拟析构函数仍然是一个很好的建议。

int main() {
    char data[sizeof(Derived)];
    if (condition)
        new (data) Derived();
    else
        new (data) Base();
    Base* ptr = reinterpret_cast<Base*>(&data[0]);
    ptr->~Base();
}

一个虚析构函数仍然是一个很好的建议。但是,如果没有动态内存分配,它将不会被使用,并且在这个类中的内存成本太高。(否则我只需在那里放置一个空的虚析构函数就可以了。) - Jason S
@Jason S: 我对此并不确定。动态分配并不总是指堆 - 它也可以意味着放置 new。我可以很容易地创建一个不使用任何动态内存分配但仍依赖于虚拟析构函数的示例。如果您绝对不能使用虚拟析构函数,则将放置 new 禁用。 - Puppy
你知道任何使用放置new而不使用动态内存分配的“简单”案例吗?这是一个具有相对有限内存且没有标准库(因此STL不在此处;我们不使用堆栈或队列或其他东西)的处理器。 - Jason S
@Jason S:你需要使用protected - 否则派生类如何在其析构函数中调用它呢? - Puppy
啊,说得好。虽然在这种情况下析构函数总是为空的,但它们只是为了防止编译器警告而存在。 - Jason S
显示剩余3条评论

2
class A
{
private:
    void *operator new(size_t);
    ...
};
operator new的其他重载和类的其余部分使用省略号。

3
或者 void* operator new(size_t) = delete; 的翻译是“禁止使用 new 运算符分配内存”。 - Andriy Tylychko
我仍然能够执行 char* addr = new char[sizeof(A)]; A* a = ::new (addr) A;。如何禁止所有的定位 new 运算符呢? - gentooise

0

只需将operator new设为私有


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接