Задать вопрос
PavelK
@PavelK

Почему ссылка на указатель даёт не верный адрес?

Приветствую!
Есть класс A
class A: public InterfaceA
{
   A() {}
   ...
   void f() {  qDebug()<<"fA"; }
}

Наследуется от чисто виртуального InterfaceA:
class InterfaceA
{
   virtual void f()=0;
}

Дальше начинается мне непонятное:

A * clA = new A();
InterfaceA * iA = clA;  

typedef InterfaceA * TIA;
void test(const TIA & I ) {
   //-- здесь "I" имеет не верный адрес, всегда на 10 больше, чем до вызова
} 
    
test(iA);

Теперь вопросы:
1. Почему при вызове test указатель по ссылке подменяется, и почему именно на 10 больше?
2. Поправка - не приходит: Почему, если сделать вместо iA = clA каст iA = static_cast(clA); поведение приходит в норму?
3. Я думал, что явного приведения при даунгрейде класса не требуется, я не прав?
4. Какие могут быть последствия, ведь если написать iA.f() вызов будет корректен ?
5. Если такое приведение не является безопасным, почему компилятор не выдал предупреждения или вообще ошибки?

UPDT1:
Выяснил, что если класс A наследуется от QObject, то при
A * clA = new A();
то в дебагере при просмотре переменной clA адрес у QObject будет например 0x9d6c78, а адрес InterfaceA 0x9d6c70 и самой переменной clA адрес будет 0x9d6c78
Если сделать InterfaceA * iA =static_cast(clA); адрес переменной iA будет 0x9d6c70 О_О
это при условии, что класс A объявлен как: public QObject, public InterfaceA
UPDT2:
Выяснилось, что вышеперечисленная особенность происходит не сразу, а спустя некоторое количество действий и внутри шаблонной магии Qt, выясняю где.

UPDT3:
В общем почему я это всё затеял - пытался отловить странный баг (сегфолт в недрах qml, куда отладчиком не подлезть).
Почему меняется указатель: скорее всего из-за множественного наследования + приколы Qt.
По багу поиск решения в процессе:
QVariant при заполнении приватной структуры data пытается заполнить поле QObject * o, но обламывается т.к. приведение типов не проходит (указатель то не тот), и когда где-то в программе (скорее всего в недрах qml) нужно сделать variant.value() то ловится сегфолт.

Осталось найти где именно идёт заполнение и как-то поспособствовать правильному касту.
Почему он считает, что InterfaceA наследуется от QObject - я его заставил, что бы работало int idd= QMetaType::type("InterfaceA*"); void *myClassPtr = QMetaType::create(idd);
  • Вопрос задан
  • 227 просмотров
Подписаться 2 Оценить Комментировать
Решения вопроса 3
Adamos
@Adamos
А на кой, простите, ляд у вас в аргументах константная ссылка на указатель?
Вот зачем именно здесь - константная ссылка?
Имхо, вы сами себя запутываете.
Передавайте указатель по значению - код упростится, и вы сами в нем разберетесь.
Сейчас, видимо, вы умудряетесь вместо указателя получить адрес самой ссылки.
Ответ написан
Если есть хоть одна виртуальна функция, то вы обязаны явно определить виртуальный деструктор.
Ответ написан
maaGames
@maaGames
Погроммирую программы
При множественном наследовании, при приведении типа выполняется гораздо больше работы, чем просто "смена типа" (изменение таблицы виртуальных функций. например). Т.е. адрес указателя на A может не совпадать с адресом указателя на TIA (хотя тот же объект передаёте). Как я понял, в реальном примере у вас множественное наследование с участием QT.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы