Jared
Jared

Reputation: 6025

Error calling function and passing a reference-to-pointer with a derived type

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.

Upvotes: 2

Views: 5246

Answers (3)

Omnifarious
Omnifarious

Reputation: 56128

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.

Upvotes: 3

Pavel Minaev
Pavel Minaev

Reputation: 101665

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

Upvotes: 3

moonshadow
moonshadow

Reputation: 89195

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.

Upvotes: 10

Related Questions