Here is the sample code.
class BaseClass {
};
class DerivedClass : public BaseClass {
};
int Foo(BaseClass*& ptr) {
}
DerivedClass* ptr_to_derived;
//following will not work
Foo(ptr_to_derived);
I fail to compile code above, and the error message is " can't convert DerivedClass* to BaseClass*&
". So How can I pass ptr_to_derived to Foo?
The error message is quite clear:
error: invalid initialization of non-const reference of type '
BaseClass*&
' from an rvalue of type 'BaseClass*
'
Because Foo
takes a pointer by non-const reference you can't pass it an rvalue. The implicit conversion from DerivedClass
to BaseClass
that happens when you pass it to Foo
gets you the rvalue that the error is complaining about.
You can create a base pointer from the derived one and pass that:
DerivedClass* ptr_to_derived;
BaseClass* ptr_derived_base = ptr_to_derived;
Foo(ptr_derived_base);
You cannot do that.
What you can do is convert to a pointer to a base, store that converted pointer somewhere (such as variable), and pass that by lvalue reference. The reference cannot refer to the derived pointer. Like so:
BaseClass* ptr_to_base = ptr_to_derived;
Foo(ptr_to_base);
However, it would be better to pass the pointer by value in order to avoid this hassle. Or preferably even pass a reference instead of a pointer to the base in case that is sufficient. Like so:
int Foo(BaseClass& ref)
With this you can call:
DerivedClass1 d1;
DerivedClass2 d2;
Foo(d1);
Foo(d2);
// or with pointers
DerivedClass1* d1_ptr = &d1;
DerivedClass2* d2_ptr = &d2;
Foo(*d1_ptr);
Foo(*d2_ptr);
The problem is that Foo
might modify the passed pointer-to-base. For example:
class OtherDerivedClass : public BaseClass {
};
OtherDerivedClass* ptr_to_other_derived = ...;
void Foo(BaseClass*& ptr)
{
ptr = ptr_to_other_derived;
}
What do you think should happen if you could call this Foo
with ptr_to_derived
? Should ptr_to_derived
now point not to a DerivedClass
but to an OtherDerivedClass
object? That's wrong on every level.
Solution 1: Don't allow Foo
to modify the pointer. Either pass by value:
void Foo(BaseClass* ptr)
or by const-ref:
void Foo(const BaseClass*& ptr)
Solution 2: Create a pointer-to-base variable that Foo
can modify.
BaseClass* ptr_to_base = ptr_to_derived;
foo(ptr_to_base);
This will of course leave ptr_to_derived
unmodified. C++ does not let you pass a temporary expression (which is what the conversion from DerivedClass*
to BaseClass*
would return) because, again, Foo
says it will modify that pointer and the changed temporary would just be discarded. That's usually a mistake. You could of course still decide to not care about the change to ptr_to_base
that Foo
might make.
This is illegal for good reasons, look at following code:
class BaseClass {};
class DerivedClass :public BaseClass {};
class DerivedClass2 :public BaseClass {};
DerivedClass2 derived2;
void Foo(BaseClass*& ptr) {
ptr = &derived2; // Legal.
}
DerivedClass* ptr_to_derived = nullptr;
then if legal, Foo(ptr_to_derived)
would make ptr_to_derived
to unrelated DerivedClass2
which is wrong.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.