这是示例代码。
class BaseClass {
};
class DerivedClass : public BaseClass {
};
int Foo(BaseClass*& ptr) {
}
DerivedClass* ptr_to_derived;
//following will not work
Foo(ptr_to_derived);
我无法编译上面的代码,并且错误消息为“ can't convert DerivedClass* to BaseClass*&
”。那么如何将ptr_to_derived传递给Foo?
答案 0 :(得分:6)
错误消息很清楚:
错误:类型的非常量引用无效的初始化 类型为“
BaseClass*&
”的右值“BaseClass*
”
由于Foo
通过非常量引用获取指针,因此无法将其传递给右值。从DerivedClass
到BaseClass
的隐式转换,当您将其传递到Foo
时,会得到错误所抱怨的右值。
您可以从派生的指针创建基本指针,然后传递该指针:
DerivedClass* ptr_to_derived;
BaseClass* ptr_derived_base = ptr_to_derived;
Foo(ptr_derived_base);
答案 1 :(得分:1)
你不能那样做。
您可以做的是将其转换为指向基的指针,将转换后的指针存储在某个位置(例如变量),然后通过左值引用传递该指针。该引用不能引用派生的指针。像这样:
BaseClass* ptr_to_base = ptr_to_derived;
Foo(ptr_to_base);
但是,最好通过值传递指针以避免这种麻烦。或者最好在足够的情况下甚至将引用而不是指针传递给基址。像这样:
int Foo(BaseClass& ref)
与此您可以致电:
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);
答案 2 :(得分:1)
问题是Foo
可能会修改传递的指向基础的指针。例如:
class OtherDerivedClass : public BaseClass {
};
OtherDerivedClass* ptr_to_other_derived = ...;
void Foo(BaseClass*& ptr)
{
ptr = ptr_to_other_derived;
}
如果您可以将Foo
称为ptr_to_derived
,您会怎么办?现在ptr_to_derived
应该不是指向DerivedClass
而是指向OtherDerivedClass
对象吗?在每个级别上都是错误的。
解决方案1::不允许Foo
修改指针。要么按值传递:
void Foo(BaseClass* ptr)
或通过const-ref:
void Foo(const BaseClass*& ptr)
解决方案2:创建指向Foo
可以修改的指向基础的变量。
BaseClass* ptr_to_base = ptr_to_derived;
foo(ptr_to_base);
这当然会使ptr_to_derived
保持不变。 C ++不允许您传递一个临时表达式(这是从DerivedClass*
到BaseClass*
的转换将返回的结果),因为Foo
再次声明它将修改该指针,而更改后的临时变量将只是被丢弃。通常这是一个错误。当然,您仍然可以决定不关心ptr_to_base
可能对Foo
所做的更改。
答案 3 :(得分:1)
出于合理原因这是非法的,请查看以下代码:
class BaseClass {};
class DerivedClass :public BaseClass {};
class DerivedClass2 :public BaseClass {};
DerivedClass2 derived2;
void Foo(BaseClass*& ptr) {
ptr = &derived2; // Legal.
}
DerivedClass* ptr_to_derived = nullptr;
然后,如果合法,Foo(ptr_to_derived)
会使ptr_to_derived
成为无关的DerivedClass2
,这是错误的。