иерархия классов и операторы new/delete

Тема в разделе "LANGS.C", создана пользователем varnie, 20 окт 2009.

  1. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    имеется иерархия классов. хочется научить ее, перегрузив операторы new/delete (и их версии для массивов), запрашивать и отдавать память через свой менеджер памяти. задача стара как мир, но я что-то несоображу, что делать в том случае наследников: операторы new/delete переопределять нельзя насколько я знаю, а потому, все наследники будут обращаться к операторам new/delete базового класса, и, скорее всего, будут нестыковки с запрашиваемым размером на аллокации, ведь sizeof(Derived_class) ,вероятно, будет больше sizeof(Base_class).
    как элегантно и грамотно поступают в этой ситуации? можно линки кинуть или показать на примерчике. благодарю.
     
  2. 0x6b65

    0x6b65 Забанен

    Публикаций:
    0
    Регистрация:
    8 окт 2009
    Сообщения:
    92
    Не будут. Но вызов delete не объект дочернего класса по указателю на базовый приведет к вызову delete родительского класса. Это надо учитывать. Можно сделать виртуальный метод SelfDestroy(), который будет вызывать delete на this, предварительно приведя его [this] к указателю на нужный тип.
     
  3. 0x6b65

    0x6b65 Забанен

    Публикаций:
    0
    Регистрация:
    8 окт 2009
    Сообщения:
    92
    P.S. Не будут потому, что они [new/delete] - статические операторы
     
  4. s0larian

    s0larian New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    489
    Адрес:
    Крыжёпполь
    varnie, то есть, operator new есть в каждом классе и ты можешь сделать свой собственный pool allocation.

    http://www.cprogramming.com/tutorial/operator_new.html
     
  5. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    varnie
    Погуглил-бы и попробовал что-ли, прежде чем спрашивать. Всё там переопределяется и размер передаётся.
     
  6. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    не рекомендуется это делать. в моей задаче мне всего лишь нужно сказать своей иерархии брать память через мой менеджер, и через него же отдавать. и не более того.
    0x6b65
    выходит, нужно переопределять их в каждом наследнике?
    с selfDestroy() как-то криво получается.
     
  7. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    varnie
    Зачем? ^) На прототип посмотри. Статический метод имеет доступ только к статическим мемберам класса.
     
  8. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    Booster
    дык, не хочется прибегать к
    Код (Text):
    1. void *Base::operator new(size_t sz) {
    2.  
    3.            if (sizeof(Base) != sz) //память задана неверно
    4.                  return ::operator new(sz); // перенаправляем в глобальный new
    5.  
    6.           //иначе выделяем по своей схеме, как и планировали
    7. }
     
  9. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    varnie
    Это ещё зачем? Размер всегда корректен.
     
  10. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    Booster
    выдержка из книги "C++ for real programmers" от Джеффа Элджера, 13-ая глава:
    Код (Text):
    1. class Foo{
    2. private:
    3.   struct FreeNode{
    4.     FreeNode *next;
    5.   };
    6.   static FreeNode* fdFreeList;
    7. public:
    8.   void* operator new(size_t bytes)
    9.   {
    10.     if (fgFreeList == NULL
    11.         return ::operator new(bytes);
    12.     FreeNode* node = fgFreeList;
    13.     fgFreeList = fgFreeList->next;
    14.     return node;
    15.   }
    16.   void operator delete(void *space)
    17.   {
    18.     ((FreeNode*)space->next = fgFreeList;
    19.     fgFreeList = (FreeNode*)space;
    20.   }
    21. }
    ...
    Код (Text):
    1. class Bar : public Foo{
    2. private:
    3.   int x;
    4. }
    Код (Text):
    1. class Foo{
    2. public:
    3.   void* operator new(size_t bytes)
    4.   {
    5.     if (bytes != sizeof(Foo) || fgFreeList == NULL)
    6.         return ::operator new(bytes);
    7.     FreeNode* node = fgFreeList;
    8.     fgFreeList = fgFreeList->next;
    9.     return node;
    10.   }
    11.   void operator delete(void *space)
    12.   {
    13.     ((FreeNode*)space->next = fgFreeList;
    14.     fgFreeList = (FreeNode*)space;
    15.   }
    16. }
    //ниже описание того, что и в operator delete нужно сделать подобные дополнения, чтобы он был тоже корректен.
    автор предлагает сл. правильный код:
    Код (Text):
    1. class Foo{
    2. private:
    3.   struct FreeNode{
    4.     FreeNode *next;
    5.   };
    6.   static FreeNode* fdFreeList;
    7. public:
    8.   virtual ~Foo(){}
    9.   void* operator new(size_t bytes)
    10.   {
    11.     if (bytes != sizeof(Foo) || fgFreeList == NULL)
    12.         return ::operator new(bytes);
    13.     FreeNode* node = fgFreeList;
    14.     fgFreeList = fgFreeList->next;
    15.     return node;
    16.   }
    17.   void operator delete(void *space, size_t bytes)
    18.   {
    19.     if (bytes != sizeof(Foo))
    20.         return ::operator delete(space);
    21.     ((FreeNode*)space->next = fgFreeList;
    22.     fgFreeList = (FreeNode*)space;
    23.   }
    24. }
     
  11. reversecode

    reversecode Guest

    Публикаций:
    0
    а если наследник не будет содержать данных а только члены класса
    то этот код сработает так же как и для базового

    тоесть это не рабочий код
    или рабочий - но токо при определенных условиях
     
  12. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Ну прям не знаю, ну заведи в каждом наследнике по своему менеджеру, перегрузка работает. Иначе использовать размер как ключ, для выбора соответствующего пула.
     
  13. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Написать макрос, которой будет переопределять операторы и указатель, и вколачивать его в каждый класс.
     
  14. letopisec

    letopisec New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2004
    Сообщения:
    228
    varnie

    хз че там Элджер пишет, но в 2005 студии в базовом классе перегружаем new и в него приходит размер базового если инстанциируем базовый и размер потомка если инстанциируем потомка.