Кто-нибудь знает, как я могу в платформенно-независимом коде C++ предотвратить создание объекта на куче? То есть, для класса "Foo" я хочу запретить пользователям делать это:
Foo *ptr = new Foo;
и разрешить им делать только это:
Foo myfooObject;
Есть ли у кого-нибудь идеи?
Будьте здоровы,
[Nick' s ответ] (https://stackoverflow.com/questions/10985/how-to-prevent-an-object-being-created-on-the-heap#11003) хорошая отправная точка, но неполный, поскольку Вы на самом деле должны перегрузить:
private:
void* operator new(size_t); // standard new
void* operator new(size_t, void*); // placement new
void* operator new[](size_t); // array new
void* operator new[](size_t, void*); // placement array new
(Хорошая кодирующая практика предложила бы, чтобы Вы также перегрузили удаление и удалить [] операторов - я был бы, но с тех пор they' ре, не собирающееся быть названным этим isn' t действительно необходимый.)
[Pauldoo] (https://stackoverflow.com/questions/10985/how-to-prevent-an-object-being-created-on-the-heap#11018) также правилен что этот doesn' t переживают соединение на Фу, хотя оно действительно переживает наследование от Фу. Вы могли сделать некоторое метапрограммное волшебство шаблона ПОМОЧЬ предотвратить это, но это не будет неуязвимо для " зло users" и таким образом вероятно, не стоит осложнения. Документация того, как это должно использоваться, и кодовый обзор, чтобы гарантировать его, используется правильно, путь на только ~100%.
Вы можете перегрузить new для Foo и сделать его приватным. Это означает, что компилятор будет стонать... если только вы не создаете экземпляр Foo на куче изнутри Foo. Чтобы поймать этот случай, вы можете просто не писать метод new для Foo, и тогда компоновщик будет стонать о неопределенных символах.
class Foo {
private:
void* operator new(size_t size);
};
PS. Да, я знаю, что это можно легко обойти. Я действительно не рекомендую это - я думаю, что это плохая идея - я просто ответил на вопрос! ;-)
Я don' t знают, как сделать это надежно и портативным способом.. но..
Если объект находится на стеке тогда, Вы могли бы быть в состоянии утверждать в конструкторе что ценность ' this' всегда близко к указателю стека. There' s хороший шанс, что объект будет на стеке, если это верно.
Я полагаю, что не все платформы осуществляют свои стеки в том же направлении, таким образом, Вы могли бы хотеть сделать одноразовый тест, когда приложение начинает проверять, какой путь стек выращивает.. Или сделайте некоторую выдумку:
FooClass::FooClass() {
char dummy;
ptrdiff_t displacement = &dummy - reinterpret_cast<char*>(this);
if (displacement > 10000 || displacement < -10000) {
throw "Not on the stack - maybe..";
}
}
[Ник] (#11003)
Это могло обойтись, создав класс, который происходит из или совокупности Фу. Я думаю, что я предлагаю (в то время как не прочный), все еще работал бы на полученные и соединяющиеся классы.
Например:
struct MyStruct {
Foo m_foo;
};
MyStruct* p = new MyStruct();
Здесь я создал случай ' Foo' на куче, обходя Foo' s скрытый новый оператор.
это может быть предотвращено, делая конструкторов частными и обеспечивая статическому участнику, чтобы создать объект в стеке
Class Foo
{
private:
Foo();
Foo(Foo& );
public:
static Foo GenerateInstance() {
Foo a ; return a;
}
}
это будет делать создание объекта всегда в стеке.
Вы могли объявить его как интерфейс и управлять классом внедрения более непосредственно из Вашего собственного кодекса.