将派生指针隐式强制转换为其相应基类的引用

Implicit casting of a derived pointer to a reference of its corresponding base

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

我有一个函数,看起来像:

// this function might modify base_ptr
void SomeFunction(shared_ptr<Base> &base_ptr)
{ if(some_condition) { base_ptr = some_other_ptr; } }

我想用shared_ptr来调用函数:

shared_ptr<Derived> d = ...;
SomeFunction(d);

这不起作用。它不工作,如果我使用普通指针(即。对Base* &从派生的*。一种解决方法是从派生指针创建一个基指针,然后将其传递给函数。

shared_ptr<Base> base = d;
SomeFunction(b);

但是从编码的角度来看,这不是很漂亮。它还增加了混淆和潜在的细微错误:

shared_ptr<Derived> d = derived;
shared_ptr<Base> b = derived;
SomeFunction(b);
// b and d might now be pointing to different things -- not good!

有更好的方法吗?

你试图做的事情本质上是危险的,c++故意让它变得困难。考虑一下c++是否允许您以想要的方式调用SomeFunction。然后你可以这样做:

struct Base {
};
struct Derived1 : Base {
  void f1();
};
struct Derived2 : Base {
  void f2();
};
void SomeFunction(shared_ptr<Base> &p)
{
  p = make_shared<Derived2>(); // nothing wrong with converting 
                               // a Derived2 pointer to a Base pointer.
}
int main()
{
  shared_ptr<Derived1> d = make_shared<Derived1>();
  SomeFunction(d); // An error, but what if it wasn't?
  d->f1(); // Trying to call method f1 of a Derived2!
}

编译器将无法知道dDerived1指针变为Derived2指针,因此当您试图调用Derived2f1方法时,它将无法给您编译错误。

你可以为智能指针的类型模板化函数

#include <iostream>
#include <memory>
#include <type_traits>
using namespace std;
class Base {
    public:
    virtual void hello() {
        cout << "hello base" << endl;
    }
};
class Derived : public Base {
    public:
    void hello() {
        cout << "hello derived" << endl;
    }
};
class otherClass {
    public:
};
template<typename T>
void SomeFunction(shared_ptr<T> &base_ptr)
{ 
    static_assert(is_base_of<Base, T>::value == true, "Wrong non-derived type");
    base_ptr->hello();
    // Rebase it
    base_ptr.reset(new Derived);
    base_ptr->hello();
}
int main() {
    shared_ptr<Base> obj(new Base());
    SomeFunction(obj);
    // hello base
    // hello derived
    shared_ptr<Derived> obj2(new Derived());
    // hello derived
    // hello derived
    SomeFunction(obj2);
    shared_ptr<otherClass> obj3(new otherClass());
    SomeFunction(obj3); // ASSERT
    return 0;
}
http://ideone.com/ATqhEZ

如果你打算在重置一个智能指针时更新所有的智能指针,你必须自己做一些簿记工作,因为它们没有被设计成具有"类似信号"的机制来通知指向同一对象的其他智能指针。


编辑了我的答案,如果你打算将它与基类和相对子类一起使用,则提供编译时安全性。

警告:上述解决方案使用c++ 11,同样可以在c++ 11之前的代码中以类似的方式完成