如何将派生类的指针传递给基类的指针?

How to pass pointer of derived class to reference to pointer of base class?

本文关键字:指针 基类 派生      更新时间:2023-10-16

这是示例代码。

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呢?

错误消息非常明确:

错误:类型的非常量引用初始化无效 'BaseClass*&' 来自类型为 'BaseClass*' 的右值

由于Foo通过非常量引用获取指针,因此无法向其传递右值。当您将其传递给Foo时,从DerivedClassBaseClass的隐式转换会让您获得错误所抱怨的右值。

您可以从派生的指针创建一个基指针并传递该指针:

DerivedClass* ptr_to_derived;
BaseClass* ptr_derived_base = ptr_to_derived;
Foo(ptr_derived_base);

问题是Foo可能会修改传递的指向基的指针。例如:

class OtherDerivedClass : public BaseClass {
};
OtherDerivedClass* ptr_to_other_derived = ...;
void Foo(BaseClass*& ptr)
{
ptr = ptr_to_other_derived;
}

如果你能用ptr_to_derived来称呼这个Foo,你认为会发生什么?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再次表示它将修改该指针,并且更改的临时表达式将被丢弃。这通常是一个错误。当然,您仍然可以决定不关心Foo可能做出的ptr_to_base更改。

你不能那样做。

您可以做的是转换为指向基的指针,将该转换后的指针存储在某个位置(例如变量),并通过左值引用传递它。引用不能引用派生的指针。这样:

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);

这是非法的,有充分的理由,请查看以下代码:

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这是错误的。