Кто-нибудь может объяснить поведение следующего кода?
b = 3
в первом случае, т.е. b2 == &d
правда?b2
а также d
и они разные. #include <iostream>
using namespace std;
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 d;
B *b2 = &d;
cout << &d << endl;
cout << b2 << endl;
const int b = (b2 == &d) ? 3 : 4; ///Case1: b = 3;
const int c = (reinterpret_cast<char*>(b2) == reinterpret_cast<char*>(&d)) ? 3 : 4; //Case 2: c = 4;
std::cout << b << c << std::endl;
return 0;
}
d имеет тип C. Когда вы преобразуете указатель на C в указатель на B, он настраивается так, чтобы он указывал на подобъект B в C (такое регулирование обычно требуется с множественным наследованием, если для B не требуется ни одного, будет один для A, поскольку C наследуется как от A, так и от B). Таким образом, во время назначения и сравнения выполняется настройка.
В два других раза &d преобразуется либо в void * (неявно), либо в char * (с reinterpret_cast), и никакие настройки не выполняются (вы явно просили об отсутствии корректировки с помощью reinterpret_cast, и нет никаких причин для выполнения корректировки при преобразовании в void *, это будет просто усложните поездку туда и обратно без веской причины, у вас снова будет аналогичный результат для А), поэтому представление будет другим.
Кстати, если бы вы использовали reinterpret_cast<B*>(&d)
Корректировка не была бы сделана снова, но использование результата в качестве B * быстро привело бы к проблемам.
В случае 1 сравнение автоматически приводит указатель C к указателю B. В этом случае это означает, что фактический адрес изменяется, так как вы используете множественное наследование, а B занимает второе место в вашем списке базовых классов. Чтобы быть более точным, указатель должен быть смещен (как минимум) на размер (A). Во втором случае, однако, такое автоматическое преобразование не выполняется, поэтому «Префикс» делает эти два указателя неравными.