Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Трата памяти на множественное наследование, Виртуальное наследование не помогает 
V
    Опции темы
EgoBrain
Дата 7.5.2013, 04:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: нет
Всего: 2



Из теории, если создается производный класс из двух, у которых общий родитель, то объект такого класса будет содержать в себе данные суперкласса два раза.
    A
  /   \
B     C
  \   /
   D (A, A)

user posted image

Так утверждает А. Л. Фридман.

Так же они утверждает что
Цитата

Базовый класс можно объявить виртуальным базовым классом
Гарантировано, что объект виртуального базового класса будет содержаться в объекте выведенного класса один раз


У меня такой вопрос, почему объект выведенного класса из обычного суперкласса меньше памяти занимает чем объект класса выведнного из виртуального суперкласса?

Код

class Parent
{
public:
    char* name;
    Parent()
    {
        name = "Parent";
    }
};

class Parent1: public Parent
{
public:

    Parent1()
    {
        a = 1; b = 2;
    }

    int a, b;
};

class Parent2: public Parent
{
public:

    int c, d;

    Parent2()
    {
        c = 3; d = 4;
    }
};

class Derived: public Parent1, Parent2
{

};

...

Derived d;
    cout<<sizeof(d);

Цитата

24


Код

...
class Parent1: public virtual Parent
...
class Parent2: public virtual Parent
...
class Derived: public Parent1, Parent2
{

};
...
Derived d;
    cout<<sizeof(d);

Цитата

28

PM MAIL ICQ Skype   Вверх
k0rvin
Дата 7.5.2013, 07:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 442
Регистрация: 24.1.2010

Репутация: нет
Всего: 5



Издержки на метаинформацию? http://ideone.com/LaJWrQ http://ideone.com/SQrSwx


--------------------
“Object-oriented design is the roman numerals of computing.” — Rob Pike
All software sucks
PM MAIL   Вверх
EgoBrain
Дата 7.5.2013, 07:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: нет
Всего: 2



Хм, что такого в моих классах?
http://ideone.com/NWBOLD
http://ideone.com/Uhjtbs
PM MAIL ICQ Skype   Вверх
math64
Дата 7.5.2013, 08:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



Variant1:
Parent: 4 bytes for name
Parent1: 4 bytes for Parent + 8 bytes for a,b = 12 bytes;
Parent2: 4 bytes for Parent + 8 bytes for c,d = 12 bytes;
Derived: 12 bytes for Parent1 + 12 bytes for Parent2 = 24 bytes;

Variant2:
Parent: 4 bytes for name
Parent1: 4 bytes for Parent* + 8 bytes for a,b + 4 bytes for Parent  = 16 bytes | 12 bytes without Parent;
Parent2: 4 bytes for Parent* + 8 bytes for c,d + 4 bytes for Parent  = 16 bytes | 12 bytes without Parent;
Derived: 12 bytes for Parent1 + 12 bytes for Parent2 + 4 bytes for Parent = 28 bytes;
PM   Вверх
EgoBrain
Дата 7.5.2013, 09:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: нет
Всего: 2



math64, почему под name всего 4 байта, когда там 6 символов?
Получается схема не верна:
user posted image
Хотя Фридман и её приводит.
То есть без виртуального наследования должно быть то что на картинке в первом посте, а с виртуальным как на этой картинке.
А по логике и по вашему ответу получается наоборот: без виртуалзиции D получил в себя даныне B и C, каждый из которых имеет данные A, потому что справедливо:
Код

Derived d;
d.Parent1::name;
d.Parent2::name;

PM MAIL ICQ Skype   Вверх
bsa
Дата 7.5.2013, 10:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(EgoBrain @  7.5.2013,  10:08 Найти цитируемый пост)
math64, почему под name всего 4 байта, когда там 6 символов?

потому что sizeof считает место занимаемое объектом, а не объем памяти используемый объектом. У тебя в объекте хранится только указатели. А данные, на которые он указывает, хранятся в статической области памяти.

В твоих примерах без виртуального наследования создавались неполиморфные классы. А в случае виртуального наследования они были полиморфными. Попробуй для начала в обоих примерах добавить в Parent виртуальный деструктор, а затем посмотри на изменения. А для наглядности еще можешь заменить char *name на char name[10].
PM   Вверх
math64
Дата 7.5.2013, 11:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



Без виртуализации Parent1 и Parent2 содержат полный класс Parent.
При виртуальном наследовании они содержат скрытые указатели на Parent, а сам Parent располагается в конце класса.
В Derived Parent имеется в одном  экемпляре и не по тому смещению, что в базовых классах, поэтому Parent1 и Parent2 должны пользоваться встроенными в них указателями для доступа к Parent.
Если добавить виртуальные методы (рекомендуется добавлять виртуальный деструктор), у каждого класса будет своя таблица вируальных методов, и даже если ты их не переопределишь в производном классе, компилятору придётся генерироватьметоды-переходники.
 Фридман в своих диаграммах эти скрытые указатели и таблицы виртульных методов не показывает,а в остальном всё правильно.
PM   Вверх
volatile
Дата 8.5.2013, 00:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(EgoBrain @  7.5.2013,  04:59 Найти цитируемый пост)
24
28


EgoBrain, добавьте в класс что н ибудь значительное, чтобы мелкие накладные расходы не затуманивали ситуацию, например
Цитата(EgoBrain @  7.5.2013,  04:59 Найти цитируемый пост)
class Parent
{
public:
    char* name;
    char something [1000];
    Parent()
    {
        name = "Parent";
    }
};

теперь все встает на свои места
Цитата
2024
1028


PM MAIL   Вверх
EgoBrain
Дата 8.5.2013, 02:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: нет
Всего: 2



Спасибо всем. Всетаки дело в служебных данных, а надежда была - вдруг что-то другое.
Попробую с деструктором поэксперементировать..
PM MAIL ICQ Skype   Вверх
math64
Дата 8.5.2013, 04:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



А также с конструктором - и посмотрите сгенрированный ассемблерный код.
Накладные расходы очень велики - так что пользуйся только когда без виртуального наследования никак.

PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0553 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.