Странное поведение при множественном наследовании QObject |
Здравствуйте, гость ( Вход | Регистрация )
Странное поведение при множественном наследовании QObject |
aljeshishe |
1.12.2009, 23:06
Сообщение
#11
|
Студент Группа: Новичок Сообщений: 12 Регистрация: 1.12.2009 Пользователь №: 1271 Спасибо сказали: 2 раз(а) Репутация: 0 |
BRE, ничего не изменилось Хм, сделал наследование каком к верху, т.е. "А" первый, тогда получаю единичку. Тут имеет значение порядок наследования. В первом случае в памяти имеем (объект класса B ): int a; <данные QObject> int b; Во втором случае: <данные QObject> int a; int b; Т.е. смещение переменной a будет разным и компилятор не может правильно рассчитать смещение при обычном привидении типа (void* -> A*). А вот если указатель сначала привести к B*, а потом к A*, то все будет нормально. Провел несколько экспериментов с порядком наследования, скажите правильно я понял, что: 1. Сначала в памяти идут виртуальные базовые классы в порядке наследования 2. затем невиртуальные классы в порядке наследования 3. в конце идет дочерний класс И еще вопросик, как располагается в памяти виртуальное наследование ? |
|
|
ViGOur |
1.12.2009, 23:20
Сообщение
#12
|
Мастер Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: 40 |
Не совсем так, получается примерно так, когда ты создаешь объект класса B создаются аргументы данного класса в такой последовательности:
после чего, когда ты приводишь объект класса B к классу A, то аргументу класса A a присваивается значение p (что тот, что другой 4 байта), так как если создать объект класса А, то создается только: Если же в классе А добавить ключевое слова virtual деструктору, то создается таблица виртуальных методов и указатель на нее, то есть получается следующая картина: и все приводится без проблем.
|
|
|
BRE |
1.12.2009, 23:23
Сообщение
#13
|
Профессионал Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: 44 |
Ой, не являюсь знатоком стандарта, поэтому точно сказать не могу. Может это прописано в стандарте, а может это остается на совести конкретного компилятора.
Попробуй найти эту информацию в книгах/интернете. Если после своего исследования отпишишся здесь, думаю не только я скажу спасибо. |
|
|
frg10 |
1.12.2009, 23:34
Сообщение
#14
|
Студент Группа: Участник Сообщений: 47 Регистрация: 8.11.2009 Из: Ростов-на-Дону Пользователь №: 1213 Спасибо сказали: 5 раз(а) Репутация: 2 |
|
|
|
Litkevich Yuriy |
1.12.2009, 23:41
Сообщение
#15
|
разработчик РЭА Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: 94 |
Если же в классе А добавить ключевое слова virtual деструктору правильно ли понимаю, что это ключевое слово не обязательно именно для деструктора, просто нужен хотя бы один виртуальный метод. А в данном примре оказалось удобнее написать его для деструктора, чтобы не изменять другие методы.
|
|
|
ViGOur |
2.12.2009, 10:30
Сообщение
#16
|
Мастер Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: 40 |
Достаточно одного виртуального метода, не обязательно деструктора, даже если этот метод в родительском классе, в производном от него классе, так же создается данная таблица.
|
|
|
aljeshishe |
2.12.2009, 17:40
Сообщение
#17
|
Студент Группа: Новичок Сообщений: 12 Регистрация: 1.12.2009 Пользователь №: 1271 Спасибо сказали: 2 раз(а) Репутация: 0 |
void* p = new B; A* a = (A*)p; Не делайте так больше никогда. Компилятор не знает ничего о том, что находится по указателю p, поэтому не может корректно привести типы. Вот так правильно:
Это была выдержка из того что используется в реальном проекте. В различных сторонних библиотеках некоторые методы могут принимать произвольные данные (void*) и эти же данные возвращать. Поскольку менять библиотеку нехорошо приходится приводить свои типы к void* P.S. Пример был создан в результате безуспешных попыток передать функции QModelIndex QAbstractItemModel::createIndex ( int row, int column, void * ptr = 0 ) свой объект и забрать его обратно через void * QModelIndex::internalPointer () const |
|
|
Litkevich Yuriy |
2.12.2009, 17:49
Сообщение
#18
|
разработчик РЭА Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: 94 |
Пример был создан в результате безуспешных попыток передать функции QModelIndex QAbstractItemModel::createIndex ( int row, int column, void * ptr = 0 ) свой объект и забрать его обратно через void * QModelIndex::internalPointer () const Хм, вроде тут всё относительно просто:
|
|
|
aljeshishe |
2.12.2009, 18:18
Сообщение
#19
|
Студент Группа: Новичок Сообщений: 12 Регистрация: 1.12.2009 Пользователь №: 1271 Спасибо сказали: 2 раз(а) Репутация: 0 |
Хм, вроде тут всё относительно просто: Согласен, сложного ничего. В моем случае в дереве хранятся объекты разных типов: пользователи содержат папки, которые содержат сообщения Пользователи при этом используют сигналы/слоты. В функциях index, data, parent модели приходится определять какой тип текущего узла. Для этого есть тип Node:
Решил использовать виртуальное наследование вместо полиморфности Node(все равботает). Правильно ли это? Хорошая статься в тему http://www.devdoc.ru/index.php/content/view/virtual_base.htm |
|
|
Litkevich Yuriy |
2.12.2009, 20:54
Сообщение
#20
|
разработчик РЭА Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: 94 |
|
|
|
Текстовая версия | Сейчас: 30.12.2024, 19:25 |