views:

197

answers:

3

Can somebody explain why the following code is not valid? Is it because the offset for the variable named d is different than the variable named b?

class Base { public: int foo; };

class Derived : public Base { public: int bar; };

int DoSomething( Base*& b ) { return b->foo; }

Base* b = new Derived;
Derived* d = new Derived;

int main()
{
   DoSomething( d );
}

This is the error that the online Comeau C++ compiler gives:

"ComeauTest.c", line 12: error: a reference of type "Base *&" (not const-qualified)
          cannot be initialized with a value of type "Derived *"
     DoSomething( d );
                  ^

This is a similar question but is different because in my example, I am declaring d as a pointer type: Passing references to pointers in C++

Note that this does compile when I pass b to DoSomething.

+6  A: 

Imagine you could do that. The reference is not const, so it's possible for DoSomething to assign to the pointer and that will be visible in the caller. In particular, inside DoSomething it's possible for us to change the pointer to point to something that isn't an instance of Derived. If the caller then tries to do Derived-specific things to the pointer after we return, it'll explode.

moonshadow
+1  A: 

This has nothing to do with offsets. Note that Derived in your example has both foo and bar as fields (and yes, they will have different offsets, but this is irrelevant here).

If this was allowed, it wouldn't be typesafe. Consider this code:

class Base { public: int foo; };

class Derived1 : public Base { public: int bar; };

class Derived2 : public Base { public: float baz; };

void DoSomething(Base*& b) { b = new Derived2; }

Derived1* d = new Derived1;
DoSomething(d); // d is of type Derived1*, but now points to object
                // of incompatible type Derived2
Pavel Minaev
+2  A: 

Suppose DoSomething were defined like this:

int DoSomething( Base*& b ) { b = new Base; }

Oops, now when main calls DoSomething, d ends up pointing at a Base and not a Derived at all.

Omnifarious