Russian Qt Forum
Ноябрь 23, 2024, 20:15 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QPoint  (Прочитано 7033 раз)
lenny
Гость
« : Сентябрь 20, 2011, 10:22 »

В исходниках Qt вот такая байда:
Код:
class Q_CORE_EXPORT QPoint
{
public:
    QPoint();
    QPoint(int xpos, int ypos);
...

#if defined(Q_OS_MAC)
    int yp;
    int xp;
#else
    int xp;
    int yp;
#endif
};
Точно не POD, зачем различное расположение данных?
« Последнее редактирование: Сентябрь 20, 2011, 10:29 от lenny » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Сентябрь 20, 2011, 11:04 »

Точно не POD, зачем различное расположение данных?
Почему не POD если виртуалов не наблюдается?
Различное расположение - видимо дань традиции (анахронизм). Вероятно когда-то xp, yp были short (qint16) - напр для совместимости со старым типом Point на Mac. См. также оператор << для QPoint 
Записан
lenny
Гость
« Ответ #2 : Сентябрь 20, 2011, 11:36 »

Класс не попадает под определение "тривиальный", т.к. присутствует пользовательский конструктор. На это и правда можно забить, но странно.
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #3 : Сентябрь 20, 2011, 11:41 »

Цитировать
The term POD class types collectively refers to aggregate classes (POD-struct types) and aggregate unions (POD-union types) that have none of the following as members [§9, ¶4]:
non-static data (including arrays) of any pointer-to-member type,
non-static data (including arrays) of any non-POD class type,
non-static data of any reference type,
user-defined copy assignment operator, nor
user-defined destructor.

The term aggregate refers to an array or class that has none of the following characteristics [§8.5.1, ¶1]:
user-declared constructors,
private or protected non-static data members,
base classes, nor
virtual functions.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Сентябрь 20, 2011, 12:39 »

Цитировать
The term POD class types collectively refers to ..
То теория пишет, а как этим пользоваться практически? Напр
Код
C++ (Qt)
struct Test {
private:
 int mA;
};
 
кто это такой? Улыбающийся Объяснять "не-полиморфный, но и не POD, а вот, мол, агрегат.." не очень удобно
Записан
lenny
Гость
« Ответ #5 : Сентябрь 20, 2011, 13:00 »

Цитировать
The term aggregate refers to an array or class that has none of the following characteristics [§8.5.1, ¶1]:
user-declared constructors,
private or protected non-static data members,
base classes, nor
virtual functions.
А это откуда? Листаю ISO 14882-2003 и не могу найти.
Записан
lenny
Гость
« Ответ #6 : Сентябрь 20, 2011, 13:03 »

Чет я засомневался об определении POD из учебников, в реальности тока добавление указателя на vtable ломает представление объекта в памяти.
Записан
lenny
Гость
« Ответ #7 : Сентябрь 20, 2011, 13:46 »

Полистав получше, пока понял, что ничего не мешает делать предположения о расположение в памяти non-POD объектов. Видать я заблуждался. Порядок декларирования в данном случае может иметь значение.
« Последнее редактирование: Сентябрь 20, 2011, 13:47 от lenny » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Сентябрь 21, 2011, 10:34 »

Можно проще, напр POD = все что сожрет "С" компилятор. А реальная/практическая разница подлежит ли RTTI или нет (можно ли создать экземпляр(ы) простым malloc).

в реальности тока добавление указателя на vtable ломает представление объекта в памяти.
Кстати там 2 указателя  (RTTI еще должен знать сам созданный объект)
Записан
lenny
Гость
« Ответ #9 : Сентябрь 21, 2011, 14:51 »

Можно проще, напр POD = все что сожрет "С" компилятор. А реальная/практическая разница подлежит ли RTTI или нет (можно ли создать экземпляр(ы) простым malloc).

в реальности тока добавление указателя на vtable ломает представление объекта в памяти.
Кстати там 2 указателя  (RTTI еще должен знать сам созданный объект)
С POD я уже не парюсь. Просто всегда думал, что в случае non-POD нельзя делать предположения о строении объекта в памяти, с чего я это взял, не пойму. В стандарте даже не нашел точного определения POD, разбросано по всему документу. Про то, что пользовательский конструктор сразу относит тип к non-POD, тоже не нашел, вроде это должно быть.
А что за второй указатель? В случае множественного наследования?
Записан
lenny
Гость
« Ответ #10 : Сентябрь 21, 2011, 15:16 »

Так вроде с помощью malloc можно все создать, причем происходит выделение памяти и для указателей на vtable. Главное, вызвать конструктор!
Код:
class A
{
public:
    virtual void f(){}
private:
    int x;
};

class B: public A
{
public:
    virtual void f()
    {
        std::cout << "is work!" << std::endl;
    }
};

int main(int argc, char **argv)
{
    B *b;
    b = (B*)malloc(sizeof(B));
    std::cout << sizeof(*b) << std::endl; //Здесь можно заметить присутствие указателя на vtable
    new(b) B;

    A *a = b;
    a->f();
}
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Сентябрь 21, 2011, 15:36 »

А что за второй указатель? В случае множественного наследования?
Ну в прынцыпе делать предположения о формате RTTI мы не можем, но здравый смысл говорит - один указатель - сам "созданный" объект (вот он может отличаться от this в случае множественного наследования), второй так называемый VMT - имея эти 2 указателя можно разобраться с dynamic_cast.

В sizeof это все входит, напр
Код
C++ (Qt)
// do not do that
void * place = malloc(sizeof(T));
T temp;
memmove(place, &temp, sizeof(T));
 
Ну понятно если T имеет члены-указатели они могут оказаться невалидны. Виртуалы для созданной "копии" позовутся корректно, а вот на dynamic_cast загнется.

Так вроде с помощью malloc можно все создать, причем происходит выделение памяти и для указателей на vtable. Главное, вызвать конструктор!
Так ведь можно это все записать в 1 операторе new  Улыбающийся - он заполняет  RTTI (а не конструктор)
Записан
lenny
Гость
« Ответ #12 : Сентябрь 21, 2011, 16:52 »

Код
C++ (Qt)
// do not do that
void * place = malloc(sizeof(T));
T temp;
memmove(place, &temp, sizeof(T));
 
Ну понятно если T имеет члены-указатели они могут оказаться невалидны. Виртуалы для созданной "копии" позовутся корректно, а вот на dynamic_cast загнется.
Почему то dynamic_cast нормально отрабатывает.
Код
C++ (Qt)
class A
{
public:
   virtual void f(){}
};
 
class B: public A
{
public:
   virtual void f(){}
};
 
int main(int argc, char **argv)
{
   B *b;
   b = (B*)malloc(sizeof(B));
   new(b) B;
 
   A *place = (A*)malloc(sizeof(B));
   memmove(place, b, sizeof(B));
   if(dynamic_cast<B*>(place))
       std::cout << "is work!" << std::endl;
 
   B b2;
 
   A *place2 = (A*)malloc(sizeof(B));
   memmove(place2, &b2, sizeof(B));
   if(dynamic_cast<B*>(place2))
           std::cout << "is work!" << std::endl;
}
 
Честно говоря, не знаю как RTTI устроен.
« Последнее редактирование: Сентябрь 21, 2011, 16:54 от lenny » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Сентябрь 21, 2011, 20:20 »

Проверим
Код
C++ (Qt)
A( void ) : mA(1) {}
   virtual void f() { mA += 1; }
 
int mA;
};
 
class B {
public:
B( void ) : mB(2) {}
   virtual void f() { mB += 2; }
 
int mB;
};
 
class C : public A, public B {
public:
C( void ) : mC(3) {}
   virtual void f() { mA += 3; }
 
int mC;
};
 
template <class T>
void PrintVMT( const char * title, T * p )
{
if (!p)
printf("%s = null", title);
else {
void ** tst = (void **) p;
printf("%s obj = %p, sizeof = %ld, VMT: ", title, p, sizeof(T));
size_t i, num = sizeof(T) / sizeof(void *);
for (i = 0; i < num; ++i)
printf("[%ld] = %p, ", i, tst[i]);
}
printf("\n");
}
 
int main(int argc, char **argv)
{
   A * a = new A;
PrintVMT("(a)", a);
 
   B * b = new B;
PrintVMT("(b)", b);
 
   C * c = new C;
PrintVMT("(c)", c);
 
A * testA = dynamic_cast <A *> (c);
PrintVMT("(testA)", testA);
 
B * testB = dynamic_cast <B *> (c);
PrintVMT("(testB)", testB);
 
return 0;
}
 

Код:
(a) obj = 0x1306340, sizeof = 8, VMT: [0] = 0x4028, [1] = 0x1, 
(b) obj = 0x1306350, sizeof = 8, VMT: [0] = 0x4040, [1] = 0x2,
(c) obj = 0x1306360, sizeof = 20, VMT: [0] = 0x4058, [1] = 0x1, [2] = 0x4064, [3] = 0x2, [4] = 0x3,
(testA) obj = 0x1306360, sizeof = 8, VMT: [0] = 0x4058, [1] = 0x1,
(testB) obj = 0x1306368, sizeof = 8, VMT: [0] = 0x4064, [1] = 0x2,

Мда, насвистел я про 2 указателя, он там 1  Улыбающийся  А разбирается он за счет уникальности ("просто B" и "B член С" имеют разные VMT)
« Последнее редактирование: Сентябрь 21, 2011, 20:23 от Igors » Записан
lenny
Гость
« Ответ #14 : Сентябрь 22, 2011, 16:42 »


Мда, насвистел я про 2 указателя, он там 1  Улыбающийся
Ничего страшного. В том и фишка, что здесь можно предполагать все, что угодно. QPoint к этому случаю не относится, а я долго избегал низкоуровневой обработки последовательностей подобных объектов.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.145 секунд. Запросов: 23.