2

Consider this example:

#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;
}

What I'm curious about is the assignB method of class C. Normally, what I'd expect with typecasting is that the (B *) this would typecast this to B* and consequently overwrite x member, not y as it does. However, this code does exactly the opposite: it properly? assigns to the B part of C.

Just tested on MSVC 2013 and GCC 4.9.2. Both behaving the same.

velis
  • 8,747
  • 4
  • 44
  • 64
  • That's a `static_cast` which is clever enough to perform the necessary pointer adjustments. Which cast did you expect to happen? A `reinterpret_cast`? – T.C. May 08 '15 at 07:35
  • Probably, yes. I just find it curious since C-stlye casting usually behaves like that. – velis May 08 '15 at 07:41

1 Answers1

2

This is because the pointer is adjusted because of the multiple inheritance.

If you print the address this would be obvious

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

Also consider using static_cast. In this case plain C style cast works as well though.

onqtam
  • 4,356
  • 2
  • 28
  • 50
  • So C++ standard defines this behaviour? I know printing the address would show what I found anyway. I'm just curious why exactly this works. – velis May 08 '15 at 07:37
  • @velis Don't you want it to work? How else would you refer to just part of a multiply inheriting class... Suppose You needed to pass pointer to an object of type C to a function that accepts only pointers to objects of type B - how else would that work? C is also a B (atleast part of it if the inheritance is public) so it should be possible – onqtam May 08 '15 at 07:41
  • Yes, I want it to work. However, C-style casting like that usually does a reinterpret_cast. That's why I'm asking. – velis May 08 '15 at 07:42
  • @velis In short: the C-style cast will try first to static_cast, but if that is not possible (types are not in the same hierarchy) it will go on and do a reinterpret_cast. Also it does a const_cast. – onqtam May 08 '15 at 07:45