Посмотрите на эту статью: Перегрузка нового в C ++ .Вы можете перегрузить оператор new
для ObjectBase
, чтобы он принимал ваш распределитель в качестве параметра и выполнял остальную часть работы:
void *ObjectBase::operator new(size_t size, Allocator *allocator) {
void *ptr = allocator->allocate(size);
// Hack to pre-initialize member before constructor is called
ObjectBase *obj = static_cast<ObjectBase *>(ptr);
obj->setAllocator(allocator);
return ptr;
}
Обычно оператор должен просто возвращать указатель навыделенной памяти, но так как вам нужен доступ к новому объекту для вызова вашего setAllocator
метода, я включил хак, который должен (но не может) работать.Обратите внимание, что фактический конструктор ObjectBase
вызывается после возврата вышеуказанной функции, поэтому вам следует убедиться, что ваш конструктор не инициализирует член-распределитель заново.
А затем аналогичная перегрузка для delete
:
void ObjectBase::operator delete(void *ptr) {
ObjectBase *obj = static_cast<ObjectBase *>(ptr);
obj->getAllocator()->free(ptr);
}
Затем вы можете создавать объекты, вызывая new (allocator) SomeClass(...)
, где SomeClass
происходит от ObjectBase
.
Edit: Одна потенциальная проблема с этим заключается в том, что выбольше не может выделять объекты в стеке, потому что нет способа инициализировать распределитель на NULL
без влияния на то, как работает перегруженный new
.
Обновление: Есть одинпоследний (грязный) взлом, чтобы заставить его работать как со стеком, так и с динамическим размещением.Вы можете сделать new
установить глобальную переменную (статический член класса также будет работать), указывающую на текущий распределитель, и конструктор может использовать это и сбросить его на NULL
.Во всех других случаях этот глобальный объект уже будет NULL
, поэтому объект, созданный в стеке, получит распределитель NULL
.
Allocator *currentAllocator = NULL;
void *ObjectBase::operator new(size_t size, Allocator *allocator) {
currentAllocator = allocator;
return allocator->allocate(size);
}
ObjectBase::ObjectBase() {
setAllocator(currentAllocator);
currentAllocator = NULL;
}