2015-05-08 4 views
2

Рассмотрим следующий пример:Почему это работает? (Множественное наследование, нарезка)

#include <iostream> 
using namespace std; 

class A 
{ 
public: 
    int x; 
}; 

class B 
{ 
public: 
    int y; 
    B() { y = 0; } 
    B(int var): y(var) {} 
}; 

class C : public A, public B 
{ 
public: 
    void assignB(B x) 
    { 
     *(B *)this = x; // <-- why does this properly assign B? 
    } 
}; 

int main() { 
    C test; 
    test.x = 5; 
    test.y = 10; 
    test.assignB(B(2)); 
    cout << "x " << test.x << endl; 
    cout << "y " << test.y << endl; 
    return 0; 
} 

Что мне интересно, это assignB метод класса C. нормально, что я бы ожидать с типажей, что (B *) this бы типаж this до B* и, следовательно, перезаписать x участник, а не y как это. Однако этот код делает точно противоположное: он правильно? присваивает B часть C.

Только что протестировано на MSVC 2013 и GCC 4.9.2. Оба ведут себя одинаково.

+0

Это 'static_cast', который достаточно умен, чтобы выполнить необходимые корректировки указателя. Какую роль вы ожидали? «Reinterpret_cast»? –

+0

Возможно, да. Я просто нахожу это любопытным, так как C-stlye casting обычно ведет себя так. – velis

ответ

2

Это потому, что указатель отрегулирован из-за множественного наследования.

Если вы печатаете адрес это было бы очевидно

cout << (long long int)(this) << endl; 
cout << (long long int)((B *)this) << endl; 

рассмотреть также с помощью static_cast. В этом случае простое выполнение стиля C также работает.

+0

Значит, C++ стандарт определяет это поведение? Я знаю, что печать адреса покажет, что я нашел в любом случае. Мне просто интересно, почему именно это работает. – velis

+0

@velis Разве вы не хотите, чтобы он работал? Как еще вы могли бы ссылаться только на часть многократно наследующего класса ... Предположим, вам нужно передать указатель на объект типа C функции, которая принимает только указатели на объекты типа B - как иначе это будет работать? C также является B (по крайней мере, частью его, если наследование открыто), поэтому должно быть возможно – onqtam

+0

Да, я хочу, чтобы он работал. Тем не менее, кастинг типа C, как обычно, делает reinterpret_cast. Вот почему я спрашиваю. – velis