隐式转换派生指针到其相应基数的引用

时间:2014-05-23 12:30:38

标签: c++ pointers

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

// 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 *&amp; from Derived *),它不起作用。一种解决方法是从Derived中创建一个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!

有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

你要做的事情本质上是危险的,而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指针,因此它无法为您提供编译错误当您尝试调用f1的方法Derived2时。

答案 1 :(得分:1)

您可以模拟智能指针类型的功能

#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

如果您打算在重置智能指针时更新所有智能指针,您将不得不自己做一些簿记,因为它们不是设计为具有“类似信号”的机制来通知其他指向智能指针同一个对象。


如果您打算将它与Base和相关子类一起使用,请编辑我的答案以提供编译时安全性。

警告:上面的解决方案使用C ++ 11 ,在C ++ 11之前的代码中也可以用类似的方式完成相同的操作