crossplatform.ru

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

2 страниц V  < 1 2  
Ответить в данную темуНачать новую тему
> struct, и ее адрес.
Iron Bug
  опции профиля:
сообщение 10.7.2015, 22:00
Сообщение #11


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

Группа: Модератор
Сообщений: 1611
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

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




Репутация:   12  


Цитата(Влад @ 10.7.2015, 15:24) *
Хмм. Имей в виду, что это поведение некоторых конкретных компиляторов, и полагаться, что так оно будет "всегда и везде" - крайне опасно.
...
Так что, вишь как, могут быть варианты.......

я думаю, что мой опыт более 20 лет профессионального программирования на С/C++ под разными системами и на разных архитектурах достаточен, чтобы понимать суть вопроса. я работала с десятками разных компиляторов, и с такими, у которых NULL был определён по-другому, и с такими, у которых char был 8 байт, и с многими другими. так что я представляю себе разнообразие возможностей, как никто другой. тут вряд ли меня можно удивить.
я не предлагаю ни на что полагаться. тем более, что мне приходится писать софт под совершенно разные процессоры и я-то точно полагаться ни на что не могу даже в рамках одного проекта. только за последние полгода я работала с пятью совершенно разными архитектурами.
но компиляторов С++ не так уж много, надо сказать. и реализаций классов тоже. я думаю, что с вероятностью 99.99%, виртуальная таблица окажется в начале, до полей членов класса. просто потому, что чисто логически её там удобнее располагать. иначе пришлось бы как-то извращаться и высчитывать, где она лежит. и хранить это смещение, опять же, в начале блока с классом :) это ничего на значит. просто логическое соображение.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 12.7.2015, 23:37
Сообщение #12


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

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




Репутация:   8  


Не ругайтесь :lol:
Только два соображения еще:
1. В самих экземплярах классов vtable не хранится, хранится только указатель.
2. При множественном наследовании может быть несколько указателей внутри класса, при этом компилятор нигде не хранит смещение, а просто генерирует код с соответствующим смещением.
Об этом кстати написано в той же статье
https://ru.wikipedia.org/wiki/Таблица_вирту....BD.D0.B8.D0.B5

Интересным следствием является то что в следующем коде
struct B1 {
    virtual ~B1() {}
};

struct B2 {
    virtual ~B2() {}
};

struct A : public B1, public B2 {
    virtual ~A() {}
};

A * aa  = new A;
B1 * b1 = aa;
B2 * b2 = aa;

b1 != b2
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 14.7.2015, 17:40
Сообщение #13


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

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

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




Репутация:   40  


Может ты имел ввиду:
b1 == b2 == aa,
но вот
b1->vptr != b2->vptr != aa->vptr
???
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 14.7.2015, 18:28
Сообщение #14


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

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




Репутация:   8  


Цитата
Может ты имел ввиду:
b1 == b2 == aa,
но вот
b1->vptr != b2->vptr != aa->vptr
???

Нет, именно b1 != b2 :lol:

->vptr у каждого свой, это да, но
b1 != b2
Для того чтобы компилировались одинаково
b->f1() и a->f1(), где
B1 *b = new B1;
B1 *a = new A;
Поскольку компилятор в момент вызова не знает, какой объект соответсвует a и b
А в момент присваивания знает, это его шанс :lol:
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 15.7.2015, 9:34
Сообщение #15


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

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

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




Репутация:   40  


Хм, может я чего не понимаю, но адрес будет один и тот же, но вот различаться будет только vptr. И при присваивании aa к b1 или b2, в зависимости от типа присваивается vptr.
Проверил в Qt Creator в отладке, адрес один и тот же. :)

Если я не прав, ткните меня в чем, чтобы закрыть пробел.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 15.7.2015, 9:37
Сообщение #16


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

Группа: Модератор
Сообщений: 1611
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

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




Репутация:   12  


да, но (*A)b1 == (*A)b2 == aa.
потому что в случае с классами для компилятора это не просто работа с указателями, а уже приведение типов и работа с виртуальными таблицами.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 15.7.2015, 11:08
Сообщение #17


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

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




Репутация:   8  


Цитата
Проверил в Qt Creator в отладке, адрес один и тот же. :)


Вот этот показывает разные адреса:
Раскрывающийся текст
struct B1 {
    virtual ~B1() {}
};

struct B2 {
    virtual ~B2() {}
};

struct A : public B1, public B2 {
    virtual ~A() {}
};

A * aa  = new A;
B1 * b1 = aa;
B2 * b2 = aa;

qDebug() << b1 << b2;


Цитата
И при присваивании aa к b1 или b2, в зависимости от типа присваивается vptr.

Вообще это связанно не столько с vptr сколько с наследованием.
Внутри объекта A содержится и B1 и B2.
Естественно, что они не могут оба начинатся по адресу aa+0.
Когда мы преобразуем указатель к B1( или B2) то мы получаем адрес объекта внутри A.
Он может быть как со смещением относительно aa так и без.
Но в любом случае эти адреса будут разными(при такой реализации наследования).
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

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


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




RSS Текстовая версия Сейчас: 29.3.2024, 1:52