имеется иерархия классов. хочется научить ее, перегрузив операторы new/delete (и их версии для массивов), запрашивать и отдавать память через свой менеджер памяти. задача стара как мир, но я что-то несоображу, что делать в том случае наследников: операторы new/delete переопределять нельзя насколько я знаю, а потому, все наследники будут обращаться к операторам new/delete базового класса, и, скорее всего, будут нестыковки с запрашиваемым размером на аллокации, ведь sizeof(Derived_class) ,вероятно, будет больше sizeof(Base_class). как элегантно и грамотно поступают в этой ситуации? можно линки кинуть или показать на примерчике. благодарю.
Не будут. Но вызов delete не объект дочернего класса по указателю на базовый приведет к вызову delete родительского класса. Это надо учитывать. Можно сделать виртуальный метод SelfDestroy(), который будет вызывать delete на this, предварительно приведя его [this] к указателю на нужный тип.
varnie, то есть, operator new есть в каждом классе и ты можешь сделать свой собственный pool allocation. http://www.cprogramming.com/tutorial/operator_new.html
varnie Погуглил-бы и попробовал что-ли, прежде чем спрашивать. Всё там переопределяется и размер передаётся.
не рекомендуется это делать. в моей задаче мне всего лишь нужно сказать своей иерархии брать память через мой менеджер, и через него же отдавать. и не более того. 0x6b65 выходит, нужно переопределять их в каждом наследнике? с selfDestroy() как-то криво получается.
varnie Зачем? ^) На прототип посмотри. Статический метод имеет доступ только к статическим мемберам класса.
Booster дык, не хочется прибегать к Код (Text): void *Base::operator new(size_t sz) { if (sizeof(Base) != sz) //память задана неверно return ::operator new(sz); // перенаправляем в глобальный new //иначе выделяем по своей схеме, как и планировали }
Booster выдержка из книги "C++ for real programmers" от Джеффа Элджера, 13-ая глава: Код (Text): class Foo{ private: struct FreeNode{ FreeNode *next; }; static FreeNode* fdFreeList; public: void* operator new(size_t bytes) { if (fgFreeList == NULL return ::operator new(bytes); FreeNode* node = fgFreeList; fgFreeList = fgFreeList->next; return node; } void operator delete(void *space) { ((FreeNode*)space->next = fgFreeList; fgFreeList = (FreeNode*)space; } } ... Код (Text): class Bar : public Foo{ private: int x; } Код (Text): class Foo{ public: void* operator new(size_t bytes) { if (bytes != sizeof(Foo) || fgFreeList == NULL) return ::operator new(bytes); FreeNode* node = fgFreeList; fgFreeList = fgFreeList->next; return node; } void operator delete(void *space) { ((FreeNode*)space->next = fgFreeList; fgFreeList = (FreeNode*)space; } } //ниже описание того, что и в operator delete нужно сделать подобные дополнения, чтобы он был тоже корректен. автор предлагает сл. правильный код: Код (Text): class Foo{ private: struct FreeNode{ FreeNode *next; }; static FreeNode* fdFreeList; public: virtual ~Foo(){} void* operator new(size_t bytes) { if (bytes != sizeof(Foo) || fgFreeList == NULL) return ::operator new(bytes); FreeNode* node = fgFreeList; fgFreeList = fgFreeList->next; return node; } void operator delete(void *space, size_t bytes) { if (bytes != sizeof(Foo)) return ::operator delete(space); ((FreeNode*)space->next = fgFreeList; fgFreeList = (FreeNode*)space; } }
а если наследник не будет содержать данных а только члены класса то этот код сработает так же как и для базового тоесть это не рабочий код или рабочий - но токо при определенных условиях
Ну прям не знаю, ну заведи в каждом наследнике по своему менеджеру, перегрузка работает. Иначе использовать размер как ключ, для выбора соответствующего пула.
Написать макрос, которой будет переопределять операторы и указатель, и вколачивать его в каждый класс.
varnie хз че там Элджер пишет, но в 2005 студии в базовом классе перегружаем new и в него приходит размер базового если инстанциируем базовый и размер потомка если инстанциируем потомка.