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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Наследование: создается один большой класс? методы и this 
:(
    Опции темы
Gunslinger
Дата 11.1.2010, 17:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 842
Регистрация: 30.12.2006
Где: Астрахань

Репутация: 1
Всего: 3



Видимо для оптимизации, методы для всех объектов одного класса создаются в единственном экземпляре. А как при множественном наследовании? Методы всех наследуемых классов компилятор организовывает в один последовательный блок памяти или нет?
Например, псевдокод:
Код

class A
{
   int d;
   int k;
   void ff(){};
}

class B
{
  double sa;
  int ms(){};
}

class C: public A, public B
{
  int g;
 int m;
 void g(){};

C obj;
};


В памяти будет вроде:
Код

struct obj
{
   int d;
   int k;
  double sa;
} 

struct С
{
   void ff(){};
   int ms(){};
   void g(){};
}
?
И вариант, когда в коде создаем не только объект-наследник, но и объекты классов А и В. 


Это сообщение отредактировал(а) Gunslinger - 11.1.2010, 17:29
PM MAIL   Вверх
xvr
Дата 11.1.2010, 17:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



С точки зрения расположения в памяти методы класса ничем не отличаются от обычных функций. И в памяти они будут лежать как обычные функции. С переменными класса эта память никак не пересекается.

PM MAIL   Вверх
mes
Дата 11.1.2010, 18:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

Репутация: 144
Всего: 250



Цитата(Gunslinger @  11.1.2010,  16:26 Найти цитируемый пост)
Видимо для оптимизации, методы для всех объектов одного класса создаются в единственном экземпляре.

нет, методы (функции члены) описываются  внутри класса фактически только для задания области видимости в отличие от дата-членов.

Код

class A
{
  public:

   static void sf ();
   void f();  
   int i;
};
A a;

фактически :
Код

namespace A // classspace A
{
   struct  this_t
   {
      int i;
   };
   void sf ();
   void f (this_t * this)
}

A::this_t a;



Это сообщение отредактировал(а) mes - 11.1.2010, 18:56


--------------------
PM MAIL WWW   Вверх
EnergoHokum
Дата 12.1.2010, 11:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Здесь неплохо расписано, как выглядит наследование C++ на низком уровне.
PM MAIL ICQ   Вверх
Gunslinger
Дата 13.1.2010, 10:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 842
Регистрация: 30.12.2006
Где: Астрахань

Репутация: 1
Всего: 3



EnergoHokum, ок.
Из статьи:
"При наследовании в результирующем классе объединяются только члены с данными! Все методы существуют в единственном экземпляре."
Я так понял, что компилятор для кода
Код

class A{
  public:
    int a1(){};
}

class B{
  public:
    int b1(){};
}      

class C: public A, public B{
  public:
    int c1(){};
}

создаст не
Код

namespace C{
   int a1(){};
   int b1(){};
   int c1(){};
}

а... "распылит", что ли, по памяти.
Код

namespace А{
  int a1(){};
}
//какая-то информация
namespace B{
  int b1(){};
}
//какая-то информация
namespace C{
  int c1(){};
}

Есть ли вообще прикладной смысл в этом знании? Какая-то мысль с приведениями указателей крутится.
PM MAIL   Вверх
zim22
Дата 13.1.2010, 11:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


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

Репутация: 24
Всего: 69



Цитата(Gunslinger @  11.1.2010,  16:26 Найти цитируемый пост)
А как при множественном наследовании?

почитай Lippman. Inside the C++ Object Model
я думаю там будет ответ на твой вопрос smile


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


любитель
****


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

Репутация: 144
Всего: 250



Цитата(Gunslinger @  13.1.2010,  09:15 Найти цитируемый пост)
а... "распылит", что ли, по памяти.

по какой памяти ? 
Код

void f1 () {}
void f2 () {}

и
Код

namespace a {
void f1 () {}
}
namespace b {
void f2 () {}
}

размещаются в памяти одинаково, только не в той памяти которую Вы судя по всему, имели ввиду.





Это сообщение отредактировал(а) mes - 13.1.2010, 12:29


--------------------
PM MAIL WWW   Вверх
Gunslinger
Дата 14.1.2010, 13:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 842
Регистрация: 30.12.2006
Где: Астрахань

Репутация: 1
Всего: 3



Цитата(zim22 @  13.1.2010,  11:13 Найти цитируемый пост)
почитай Lippman. Inside the C++ Object Model
я думаю там будет ответ на твой вопрос smile 

Нашел Липпмана, которого ты в прошлой теме советовал, но по отзывам в переводе неточности, а в коде встречаются ошибки. Так что я не рискнул. Эту книгу только на торрентсе нашел, пока не скачал.

Цитата(mes @  13.1.2010,  12:08 Найти цитируемый пост)
по какой памяти ? 

Тогда в адресном пространстве?smile Друг за другом, вроде: по адресу 1 - метод класса А, по адресу 2 - метод класса В, по адресу 3 - метод класса С (в каждом по одному методу). Если так, тогда понятно, почему можно сделать так:
Код

class A{public: a1(){};
};
class B{public: b1(){};
};
class C: public A, public B {public: c1(){}
};

С *pC=new C;
pC->c1();
A *pA=(A)pC;
pA->a1();

ps. Возможны синтаксические неточности.

Это сообщение отредактировал(а) Gunslinger - 14.1.2010, 13:13
PM MAIL   Вверх
mes
Дата 14.1.2010, 13:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

Репутация: 144
Всего: 250



Цитата(Gunslinger @  14.1.2010,  12:11 Найти цитируемый пост)
Тогда в адресном пространстве?

Цитата(Gunslinger @  14.1.2010,  12:11 Найти цитируемый пост)
Если так, тогда понятно,

Ваш пример не понял.. можете объяснить, как создание объекта связано с расположением функций(-членов)?




--------------------
PM MAIL WWW   Вверх
zim22
Дата 14.1.2010, 13:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


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

Репутация: 24
Всего: 69



Цитата(Gunslinger @  14.1.2010,  12:11 Найти цитируемый пост)
Нашел Липпмана, которого ты в прошлой теме советовал,

то другая книга

Цитата(Gunslinger @  14.1.2010,  12:11 Найти цитируемый пост)
 но по отзывам в переводе неточности, а в коде встречаются ошибки

перевод очень хорош. в коде есть пара ошибок, но они легко обнаруживаются



--------------------
PM MAIL   Вверх
Gunslinger
Дата 14.1.2010, 13:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 842
Регистрация: 30.12.2006
Где: Астрахань

Репутация: 1
Всего: 3



Цитата(zim22 @  14.1.2010,  13:18 Найти цитируемый пост)
перевод очень хорош. в коде есть пара ошибок, но они легко обнаруживаются

Тогда сегодня скачаю, заодно и по объектной модели.

Цитата(mes @  14.1.2010,  13:14 Найти цитируемый пост)
Ваш пример не понял.. можете объяснить, как создание объекта связано с расположением функций(-членов)?

Попробую... Вот мои мысли:
1. Приведение указателя -- адрес остается тем же, только меняется тип. Т.е. указывал на участок памяти одного размера (начиная с какого-то адреса), теперь указывает на участок памяти другого размера (при этом, начиная с того же самого адреса). 
2. Наследование С: public A, pubic B, ... . Методы классов родителей и наследника объединяются и располагаются в памяти друг за другом, в порядке списка наследования -- сначала А, затем В и С. Таким образом с помощью указателя можно получать доступ к методам не только наследника, но и всех его родителей, перемещаясь по этой области памяти. То есть тот же самый код:
Код

С *pC=new C; // -- Выделили область памяти для всех методов: и наследника, и родителей  
pC->c1();// -- Обратились к методу наследника. Как обычно
A *pA=(A)pC;// -- Теперь указатель чуть меньшего размера, чем область С, при этом начальный адрес тот же, что и у pC
pA->a1(); //-- Таким образом получили доступ к методу одного из родителе, к А.



PM MAIL   Вверх
xvr
Дата 14.1.2010, 14:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата

Попробую... Вот мои мысли:
Странные у вас мысли  smile Кажется у вас путанница в некоторых базовых понятиях - методы объектов НЕ ЛЕЖАТ вместе с их данными. Они вообще никак не привязанны к конкретным экземплярам этих объектов. При наследовании объектов методы родителя остаются как были, никто никаких новых экземпляров этих методов не создает.
Методы - это ОБЫЧНЫЕ функции с неявным дополнительным формальным параметром.

PM MAIL   Вверх
Gunslinger
Дата 14.1.2010, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 842
Регистрация: 30.12.2006
Где: Астрахань

Репутация: 1
Всего: 3



Цитата(xvr @  14.1.2010,  14:17 Найти цитируемый пост)
методы объектов НЕ ЛЕЖАТ вместе с их данными. 

Я не писал о данных. При чем здесь они? Я уже знаю, что они лежат отдельно, а у методов есть this на них. 

Цитата(xvr @  14.1.2010,  14:17 Найти цитируемый пост)
При наследовании объектов методы родителя остаются как были, никто никаких новых экземпляров этих методов не создает.

Вот это я и хочу понять. Получается, например, так: есть 2 класса и есть класс 3 - их наследник. Копию родителей не создает, понятно. А как располагает в адресном пространстве? Друг за другом или нет?
PM MAIL   Вверх
mes
Дата 14.1.2010, 15:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

Репутация: 144
Всего: 250



Цитата(Gunslinger @  14.1.2010,  12:52 Найти цитируемый пост)
Попробую... Вот мои мысли:

зря Вы перешли к множественному наследованию не разобравшись с классическим.


Цитата(Gunslinger @  14.1.2010,  12:52 Найти цитируемый пост)
Приведение указателя -- адрес остается тем же, только меняется тип. Т.е. указывал на участок памяти одного размера (начиная с какого-то адреса), теперь указывает на участок памяти другого размера (при этом, начиная с того же самого адреса). 


При множественном наследовании это не так. Адрес меняется.
Код


struct A { int i; };
struct B { int i; };
struct AB : A, B {};

int main() {

AB ab;
std::cout  << (A*)&ab << " "<<  (B*)&ab << std::endl;
}


Цитата(Gunslinger @  14.1.2010,  12:52 Найти цитируемый пост)
Методы классов родителей и наследника объединяются и располагаются в памяти друг за другом

Какое отношение расположение методов имеет к указателю this ? какой бы ни был this методы всегда продолжают лежать на своем месте, и
Цитата(xvr @  14.1.2010,  13:17 Найти цитируемый пост)
методы объектов НЕ ЛЕЖАТ вместе с их данными


Цитата(Gunslinger @  14.1.2010,  12:52 Найти цитируемый пост)
Таким образом с помощью указателя можно получать доступ к методам не только наследника

Кажись я понял в чем дело.. Вас сбила терминология. 

Есть два разных добирания... Когда речь идет о добирании до методов, роль играет не значение указателя (оно может бытэ любым хоть NULL), а его тип.
И второе добирание, когда функция-член посредством this хочет добраться до данных. 
В примере ниже мы не используем ни виртуальных ни данных объекта, поэтому смело можем передавать NULL в качестве аргумента.
(но не забываем что пример тестовый и в реале подобный подход не рекомендуется)
И в зависимости от приведения у нас выберется нужная функция.

Код

struct A {  void f (){ std::cout << 1; } };
struct B {  void f (){ std::cout << 2; } };
struct AB : A, B {};

int main() {

AB * ab = NULL;
//   ab->f(); // request for member `f' is ambiguous
            // так как обе  f одинаково подходят.   
   
 ((A*) ab) ->f();
 ((B*) ab) ->f(); 
}







--------------------
PM MAIL WWW   Вверх
mes
Дата 14.1.2010, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

Репутация: 144
Всего: 250



Цитата(Gunslinger @  14.1.2010,  14:33 Найти цитируемый пост)
А как располагает в адресном пространстве? Друг за другом или нет? 

данные друг за другом с учетом выравнивания, а функции(-члены) где вздумается.
Более того на самом деле генерируется на много больше функций, чем Вы видете в коде.




--------------------
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

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

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


 




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


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

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