#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
Re: Странное повдение при множественном наследовании QObject
Здравствуйте, yx2006, Вы писали:
Y>Здравствуйте, kinetix, Вы писали:
K>>int main(int argc, char* argv[]) K>>{ K>> void* p = new B;
Y>
Y>B* p = new B;
Y>
K>> A* a = (A*)p;
K>>В конце значение с неопределено. Если не наследовать от QObject то все нормально с=1. msvc-2008, qt-4.5.0
Y>а что тут странного? Откуда комилятор догадается, что твой void — это B
Ну как-то видимо догадывается K>>Если не наследовать от QObject то все нормально с=1
Проблема именно с QObject и void*.
Re[3]: Странное повдение при множественном наследовании QObj
От:
Аноним
Дата:
01.12.09 17:33
Оценка:
Здравствуйте, kinetix, Вы писали:
K>Ну как-то видимо догадывается K>>>Если не наследовать от QObject то все нормально с=1 K>Проблема именно с QObject и void*.
С чего ты вззял?
Как ты думаешь, что будет, если ты будешь наследываться не от QObject,
а от своего полиморфного класса?
Re[4]: Странное повдение при множественном наследовании QObj
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, kinetix, Вы писали:
K>>Ну как-то видимо догадывается K>>>>Если не наследовать от QObject то все нормально с=1 K>>Проблема именно с QObject и void*.
А>С чего ты вззял? А>Как ты думаешь, что будет, если ты будешь наследываться не от QObject, А>а от своего полиморфного класса?
Спасибо, намек понял
Re[3]: Странное повдение при множественном наследовании QObj
Здравствуйте, kinetix, Вы писали:
K>Ну как-то видимо догадывается K>>>Если не наследовать от QObject то все нормально с=1 K>Проблема именно с QObject и void*.
Проблема в множественном наследовании. И это твоя проблема, а не QObject. Ты контроль типов нарушил, а теперь платишь за последствия.
Лучше объясни зачем тебе такие фокусы понадобились?
Re[3]: Странное повдение при множественном наследовании QObj
Y>>а что тут странного? Откуда комилятор догадается, что твой void — это B
K>Ну как-то видимо догадывается K>>>Если не наследовать от QObject то все нормально с=1 K>Проблема именно с QObject и void*.
в первом случае тебе просто повезло. Сравни с:
void* z = new int;
*(int*)z = 1;
A* zz = (A*)z;
int c1 = zz->a;
казалось бы, где здесь объект A
Re[4]: Странное повдение при множественном наследовании QObj
Здравствуйте, wander, Вы писали:
W>Здравствуйте, kinetix, Вы писали:
K>>Ну как-то видимо догадывается K>>>>Если не наследовать от QObject то все нормально с=1 K>>Проблема именно с QObject и void*.
W>Проблема в множественном наследовании. И это твоя проблема, а не QObject. Ты контроль типов нарушил, а теперь платишь за последствия.
W>Лучше объясни зачем тебе такие фокусы понадобились?
Ну понятно дело, я компилятор не обвиняю в неправильной работе, у меня не такой большой опыт для это.
Просто столкнулся с тем что реальная работа отличается от моих представлений.
Короче реально работать будут 2 варианта:
#include <QObject>
class A
{
public:
A(): a(1){};
//virtual ~A(){};
int a;
};
class B : virtual public QObject, public A
{
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;
}
#include <QObject>
class A
{
public:
A(): a(1){};
virtual ~A(){};
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 должен наследоваться первым, то выбираем первый.
Поправьте, если я не прав. Вопрос на засыпку: чем черевато виртуальное наследование.
P.S.
Пример был создан в результате безуспешных попыток передать функции QModelIndex QAbstractItemModel::createIndex ( int row, int column, void * ptr = 0 ) свой объект и забрать его обратно через void * QModelIndex::internalPointer () const
Re: Странное повдение при множественном наследовании QObject
K>Поскольку QObject должен наследоваться первым, то выбираем первый. K>Поправьте, если я не прав. Вопрос на засыпку: чем черевато виртуальное наследование.
ежики плакали, кололись, но продолжали есть кактус
замени в своем первоначальном "неправильном" примере строку
A* a = (A*)p;
на
A* a = (A*)(B*)p;
и удивись
ЗЫ. Домашнее задание: понять, почему так происходит
Re[5]: Странное повдение при множественном наследовании QObj
Здравствуйте, kinetix, Вы писали:
K>Ну понятно дело, я компилятор не обвиняю в неправильной работе, у меня не такой большой опыт для это. K>Просто столкнулся с тем что реальная работа отличается от моих представлений. K> Короче реально работать будут 2 варианта:
K>
K>#include <QObject>
K>class A
K>{
K>public:
K> A(): a(1){};
K> //virtual ~A(){};
K> int a;
K>};
K>class B : virtual public QObject, public A
K>{
K>public:
K> B():A(), b(2){};
K> int b;
K>};
K>int main(int argc, char* argv[])
K>{
K> void* p = new B;
K> A* a = (A*)p;
K> int c = a->a;
K> return 0;
K>}
K>
K>
K>#include <QObject>
K>class A
K>{
K>public:
K> A(): a(1){};
K> virtual ~A(){};
K> int a;
K>};
K>class B : public A, public QObject
K>{
K>public:
K> B():A(), b(2){};
K> int b;
K>};
K>int main(int argc, char* argv[])
K>{
K> void* p = new B;
K> A* a = (A*)p;
K> int c = a->a;
K> return 0;
K>}
K>
K>Поскольку QObject должен наследоваться первым, то выбираем первый. K>Поправьте, если я не прав. Вопрос на засыпку: чем черевато виртуальное наследование. K>P.S. K>Пример был создан в результате безуспешных попыток передать функции QModelIndex QAbstractItemModel::createIndex ( int row, int column, void * ptr = 0 ) свой объект и забрать его обратно через void * QModelIndex::internalPointer () const
Для начала цитата из документации по QT функции createIndex. Ты об этом знаешь?
It is not advisable to access the internal pointer in the index outside of the model. Use the data() function instead.
Во-вторых, еще раз: не приводи полиморфные и множественно наследованные классы к void*.
Если так хочется, то лучше делать так:
class A
{
public:
A() : a(1) {}
int getA() {return a; }
private:
int a;
};
class B
: public A, public QObject
{
public:
B() : b(2) {}
int getB() {return b; }
private:
int b;
};
template <typename C>
class StorageHelper
{
public:
explicit StorageHelper(C * ptr)
: ptr_(ptr)
{}
explicit StorageHelper(std::auto_ptr<C> ptr)
: ptr_(ptr)
{}
C * operator->() const// доступ к членам хранимого класса
{
return ptr_.get();
}
void * toVoid() // каст к void*
{
return reinterpret_cast<void*>(this);
}
static StorageHelper<C> & fromVoid(void * p) // обратно к классу хелпера
{
return *reinterpret_cast<StorageHelper<C> *>(p);
}
private:
StorageHelper();
StorageHelper(StorageHelper const &); // лучше запретить копирование для этого класса
StorageHelper & operator=(StorageHelper const&);
std::auto_ptr<C> ptr_;
};int main()
{
StorageHelper<A> st(new B);
void * p = st.toVoid();
//...// здесь нужно обеспечить чтобы st был еще жив.
// и совершенно не стоит пытаться делать что-то наподобие:
// StorageHelper<B>::fromVoid(p) без сооветствующего StorageHelper<B> st(new B);
// это приведет к непредсказуемым последствиям.
StorageHelper<A> & st_ref = StorageHelper<A>::fromVoid(p);
int c = st_ref->getA();
std::cout << c << std::endl;
return 0;
}
Re[6]: Странное повдение при множественном наследовании QObj
W>Для начала цитата из документации по QT функции createIndex. Ты об этом знаешь? W>
W>It is not advisable to access the internal pointer in the index outside of the model. Use the data() function instead.
Да, насчет этого я в курсе. Все действия происходят внутри модели, свой код писал по примерам qt, так что наверное в использовании internalPointer() ничего страшного. W>Во-вторых, еще раз: не приводи полиморфные и множественно наследованные классы к void*.
Тысячу раз согласен что void* — зло, но в данном случае qt хранит указатель на данные конкретного QModelIndex'a именно в таком виде. W>Если так хочется, то лучше делать так:
Честно пытался разобраться в Вашем примере. Если я правильно Вас понял, смысл состоит в использовании интеллектуального указателя и в инкапсуляции преобразований к void* и обратно в отдельный класс.
Наверное такой вариант мне не совсем подойдет, поскольку, насколько я знаю, auto_ptr действует пределах области видимости. В то время как я создаю QModelIndex в одном месте (QAbstractItemModel::index), а получаю из него указатель в другом (QAbstractItemModel::data).
Re[7]: Странное повдение при множественном наследовании QObj
Здравствуйте, kinetix, Вы писали:
K>Тысячу раз согласен что void* — зло, но в данном случае qt хранит указатель на данные конкретного QModelIndex'a именно в таком виде.
Дело не в том, что void * — зло, а в том, что ill-formed код у тебя получается со всеми вытекающими.
K>Честно пытался разобраться в Вашем примере. Если я правильно Вас понял, смысл состоит в использовании интеллектуального указателя и в инкапсуляции преобразований к void* и обратно в отдельный класс.
Основная идея там в том, чтобы завернуть твои полиморфные указатели в такой хелпер. И обеспечить сравнительно безопасное преобразование на его уровне в void * и обратно. Сохранив при этом контроль типов для хранимого указателя. auto_ptr там тоже совсем не обязателен, если ты не предполагаешь на этом уровне контролировать время жизни.
K>Наверное такой вариант мне не совсем подойдет, поскольку, насколько я знаю, auto_ptr действует пределах области видимости. В то время как я создаю QModelIndex в одном месте (QAbstractItemModel::index), а получаю из него указатель в другом (QAbstractItemModel::data).