|
|
Регистрация Восстановить пароль |
Повторная активизация e-mail |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
|
|
Опции темы | Поиск в этой теме |
17.05.2013, 00:41 | #1 |
Регистрация: 17.05.2013
Сообщений: 3
|
наследование и указатели
вопрос наверное очень простой, но не могу понять
Код:
1. Создаётся первый объект Derived, размещается в куче 2. Создаётся второй объект Derived, размещается в куче через n байтов, где n - размер класса Base. 3. из-за такого размещения теряется информация о значении value для первого объекта Derived, для второго всё в порядке почему для второго объекта не выводится значение value? объясните пожалуйста, в чем ошибка в моих рассуждениях, или посоветуйте что почитать на эту тему |
17.05.2013, 07:55 | #2 | ||
Белик Виталий :)
Старожил
Регистрация: 23.07.2007
Сообщений: 57,097
|
Цитата:
Цитата:
Я думаю должно быть так: Код:
I'm learning to live...
|
||
17.05.2013, 15:01 | #3 |
Форумчанин
Регистрация: 03.01.2013
Сообщений: 388
|
for(int i=0;i<2;i++) arrayOfDerived[i] = new Derived();
Ошибка. Вы не присваиваете память указателю, вы его разыменовываете и пытаетесь сделать так, что бы он указывал на память выделенную под Derived. |
17.05.2013, 16:04 | #4 | |
Старожил
Регистрация: 25.10.2011
Сообщений: 3,178
|
Цитата:
1) В куче выделяется место, достаточное для размещения двух объектов типа Derived. 2) Дважды вызывается конструктор Derived без параметров, инициализируя два элемента этого массива. 3) Указатель на первый элемент присваивается переменной arrayOfDerived. 4) При вызове arrayOfDerived[0].print() вычисляется arrayOfDerived[0], трактуется как объект типа Base и для него вызывается print(). Если не изменяет память, стандарт не гарантирует корректной работы такого кода (не уверен). В случае Visual Studio 2010, однако, он отрабатывает нормально и выводит 5 (т.е. успешно вызвалась Derived:: print(), и успешно обратилась к значению value). 5) При вызове arrayOfDerived[1].print(), однако, начинаются интересные вещи. Ведь компилятор высчитывает положение второго элемента массива как "начало массива плюс размер первого элемента". А размер в этом случае вычисляется статически, то есть смещение равно sizeof(Base). В итоге arrayOfDerived[1] начинается непонятно где, и поведение программы становится вполне неопределённым. Однако, в реальном случае, мы получим, что там, где ожидался указатель на таблицу виртуальных функций объекта, оказался "хвост" от Derived: значение 5. После чего программа попытается обратиться по адресу 0x00000005 с весьма предсказуемыми последствиями. 6) Однако даже если закомментировать эту строку, остаётся фундаментальная причина, по которой так писать нельзя: деструкторы. Когда будет вызван delete[] arrayOfDerived, компилятор сгенерирует код, который вызовет деструкторы для arrayOfDerived[0] и arrayOfDerived[1], ровно с той же проблемой при вычислении границ arrayOfDerived[1]. |
|
17.05.2013, 16:15 | #5 |
Форумчанин
Регистрация: 03.01.2013
Сообщений: 388
|
4) А почему объект типа Base? Там ведь позднее связывание срабатывает. Тогда, будет вызван метод для объекта того типа на который указывает указатель типа Base...
или я чего-то недопонял... |
17.05.2013, 16:21 | #6 | |
Старожил
Регистрация: 25.10.2011
Сообщений: 3,178
|
Цитата:
Р-р-р... третий пост, и третий смайлик подряд. Достало. |
|
17.05.2013, 16:24 | #7 | |
Форумчанин
Регистрация: 03.01.2013
Сообщений: 388
|
Естественно, но почему Вы написали, что
Цитата:
|
|
17.05.2013, 16:37 | #8 | ||
Старожил
Регистрация: 25.10.2011
Сообщений: 3,178
|
Цитата:
|
||
17.05.2013, 18:50 | #9 | |
Старожил
Регистрация: 13.07.2012
Сообщений: 6,331
|
Цитата:
ptr + sizeof(Base) (а не Derived) в результате чего, указатель указывает кудато не туда. В С/С++ нельзя делать массивы разных типов. Если масив Base, значит все елементы Base, если Derived, тогда Derived. В данном случае надо делать массив из указателей: Base* array[2]; array[0] = new Derive; array[1] = new Derive; Ну и сам массив можно выделять динамически, если надо. |
|
17.05.2013, 20:05 | #10 | |
Белик Виталий :)
Старожил
Регистрация: 23.07.2007
Сообщений: 57,097
|
Цитата:
I'm learning to live...
|
|
|
Похожие темы | ||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Наследование в С++ | Theseus | Общие вопросы C/C++ | 10 | 21.07.2012 20:06 |
Наследование | Настюнечка | Помощь студентам | 0 | 29.11.2011 18:40 |
наследование | настюх | Помощь студентам | 8 | 27.11.2011 13:54 |
Наследование | Сергей089 | Помощь студентам | 6 | 07.02.2010 12:04 |
[C] массивы, указатели, двойные указатели. | Iggel | Общие вопросы C/C++ | 5 | 05.05.2009 12:39 |