crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

3 страниц V   1 2 3 >  
Ответить в данную темуНачать новую тему
> Странное поведение при множественном наследовании QObject
aljeshishe
  опции профиля:
сообщение 1.12.2009, 19:52
Сообщение #1


Студент
*

Группа: Новичок
Сообщений: 12
Регистрация: 1.12.2009
Пользователь №: 1271

Спасибо сказали: 2 раз(а)




Репутация:   0  


#include <QObject>
class A
{
public:
    A(): a(1){};
    int a;

};

class B :   public A, public QObject
{
public:
    B():A(), b(2){};
    int b;
};
int main(int argc, char* argv[])
{
    void* p = new B;
    A* a = (A*)p;
    int c = a->a;
    return 0;
}

В конце значение с неопределено. Если не наследовать от QObject то все нормально с=1. msvc-2008, qt-4.5.0
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 1.12.2009, 20:10
Сообщение #2


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(aljeshishe @ 1.12.2009, 22:52) *
class B : public A, public QObject
порядок наследования неверный, QObject должен быть всегда первым, читай доку
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
aljeshishe
  опции профиля:
сообщение 1.12.2009, 20:20
Сообщение #3


Студент
*

Группа: Новичок
Сообщений: 12
Регистрация: 1.12.2009
Пользователь №: 1271

Спасибо сказали: 2 раз(а)




Репутация:   0  


Цитата(Litkevich Yuriy @ 1.12.2009, 20:10) *
Цитата(aljeshishe @ 1.12.2009, 22:52) *
class B : public A, public QObject
порядок наследования неверный, QObject должен быть всегда первым, читай доку

Пробовал и так, результат тот же
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 1.12.2009, 20:55
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Добавь магическую строку:
#include <QObject>
class A
{
public:
    A(): a(1){};
        virtual ~A() {}

    int a;

};

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 1.12.2009, 21:03
Сообщение #5


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


BRE, ничего не изменилось

Хм, сделал наследование каком к верху, т.е. "А" первый, тогда получаю единичку.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
aljeshishe
  опции профиля:
сообщение 1.12.2009, 21:07
Сообщение #6


Студент
*

Группа: Новичок
Сообщений: 12
Регистрация: 1.12.2009
Пользователь №: 1271

Спасибо сказали: 2 раз(а)




Репутация:   0  


Цитата(BRE @ 1.12.2009, 20:55) *
Добавь магическую строку:
#include <QObject>
class A
{
public:
    A(): a(1){};
        virtual ~A() {}

    int a;

};

Спасибо, как я понял дело в полиморфности QObject. Поясните если не трудно для чего нужна полиморфность класса А.

Цитата(BRE @ 1.12.2009, 20:55) *
Добавь магическую строку:
#include <QObject>
class A
{
public:
    A(): a(1){};
        virtual ~A() {}

    int a;

};

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 1.12.2009, 21:09
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(aljeshishe @ 1.12.2009, 21:07) *
Спасибо, как я понял дело в полиморфности QObject. Поясните если не трудно для чего нужна полиморфность класса А.

Для того, что-бы компилятор смог правильно вычислить смещение до переменной a.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
aljeshishe
  опции профиля:
сообщение 1.12.2009, 21:20
Сообщение #8


Студент
*

Группа: Новичок
Сообщений: 12
Регистрация: 1.12.2009
Пользователь №: 1271

Спасибо сказали: 2 раз(а)




Репутация:   0  



Спасибо
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 1.12.2009, 21:30
Сообщение #9


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(Litkevich Yuriy @ 1.12.2009, 21:03) *
BRE, ничего не изменилось

Хм, сделал наследование каком к верху, т.е. "А" первый, тогда получаю единичку.

Тут имеет значение порядок наследования.
В первом случае в памяти имеем (объект класса B ):
int a;
<данные QObject>
int b;

Во втором случае:
<данные QObject>
int a;
int b;

Т.е. смещение переменной a будет разным и компилятор не может правильно рассчитать смещение при обычном привидении типа (void* -> A*).
А вот если указатель сначала привести к B*, а потом к A*, то все будет нормально.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 1.12.2009, 21:43
Сообщение #10


Мастер
******

Группа: Модератор
Сообщений: 3296
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Цитата(BRE @ 1.12.2009, 21:09) *
Для того, что-бы компилятор смог правильно вычислить смещение до переменной a.
Точней будет, что ключевое слово virtual добавляет в класс А таблицу виртуальных методов (vtable), благодаря чему при приведении класса B к классу А смещение считается правильно. А без этого ключевого слова класс А был без этой таблицы. :)

Если я правильно все понял!

А вот и более точный ответ:
Цитата
Обычно компилятор создает отдельную vtable для каждого класса. После создания объекта указатель на эту vtable, называемый виртуальный табличный указатель или vpointer, добавляется как скрытый член данного объекта (а зачастую как первый член). Компилятор также генерирует "скрытый" код в конструкторе каждого класса для инициализации vpointer'ов его объектов адресами соответствующей vtable.
:)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

3 страниц V   1 2 3 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 28.3.2024, 23:04