Может ли кто-нибудь объяснить, как в этом коде работает переинтерпретация приведения?

прочитайте следующую программу, которая использует reinterpret_cast.

#include <iostream>

class A
{
   public:
      A() : m_i(0) { }
   protected:
      int m_i;
};

class B
{
   public:
      B() : m_d(0.0) { }

   protected:
      double m_d;
};

class C : public A , public B
{
   public:
      C() : m_c('a') { }
   private:
      char m_c;
};

int main()
{
   C c;
   A *pa = &c;
   B *pb = &c;

   bool z = (reinterpret_cast<char*>(pa) == reinterpret_cast<char*>(pb));
   std::cout << z;
   return 0;
}

После запуска этой программы она печатает 0, кто-нибудь может объяснить, почему в этой программе z становится ложным??


person luck    schedule 08.10.2015    source источник


Ответы (2)


Может ли кто-нибудь объяснить, как в этом коде работает переинтерпретация приведения?

reinterpret_cast<char*>(pa) оценивается как указатель типа char*, числовое значение которого такое же, как у pa. Использование:

bool z = (pa == pb);

приводит к ошибке компилятора, поскольку A и B не связаны напрямую. Использование

bool z = (reinterpret_cast<char*>(pa) == reinterpret_cast<char*>(pb));

позволяет сравнить числовые значения pa и pb.

После запуска этой программы она печатает 0, кто-нибудь может объяснить, почему в этой программе z становится ложным??

Числовые значения pa и pb не совпадают. Отсюда и результат. Вы можете использовать:

cout << "pa: " << std::hex << (void*)pa << std::endl;
cout << "pb: " << std::hex << (void*)pb << std::endl;

чтобы напечатать эти значения и убедить себя, что они не совпадают.

Если вы посмотрите на структуру памяти C, она выглядит примерно так:

+------+
|  m_i |     // The A sub-object
+------+
|  m_d |     // The B sub-object
+------+
|  m_c |     
+------+

Когда вы используете

C c;
A* pa = &c;
B* pb = &c;

pa указывает на подобъект A объекта C, а pb указывает на подобъект B объекта C. Как видно из рисунка, между подобъектом A и подобъектом B есть смещение. Следовательно, числовые значения pa и pb различны. Скорее всего отличаются на sizeof(m_i).

person R Sahu    schedule 08.10.2015
comment
@R Саху, почему значение pa и pb разное. Они имеют одинаковый адрес значения c (&c) - person luck; 08.10.2015
comment
Я не думаю, что bool z = (pa == pb); будет компилироваться, так как A и B не являются производными друг от друга, и поэтому указатель A* нельзя напрямую сравнивать с указателем B* без приведения их к общему типу данных, в данном случае char*. - person Remy Lebeau; 08.10.2015

reinterpret_cast здесь такой же, как static_cast. reinterpret_cast происходит во время выполнения, а static_cast — во время компиляции. В данном случае это не имеет значения, но имело бы значение, если бы приведение было применено к объекту c.

A* pa = &reinterpret_cast<A&>(c); 
B* pb = &reinterpret_cast<B&>(c); 

сделали бы pa и pb одинаковыми. В то время как то, что вы написали, эффективно выполняет неявное статическое приведение:

A* pa = &static_cast<A&>(c); 
B* pb = &static_cast<B&>(c);

А так как это делает pa и pb разными, то не имеет значения, что их потом «переинтерпретируют».

person Dmitry Rubanovich    schedule 08.10.2015