boost :: shared_ptr和继承

时间:2011-03-03 13:15:44

标签: c++ inheritance shared-ptr

我面临的情况是我有std::vectorboost::shared_ptr个基类。在我的程序过程中,我需要将共享指针存储到该向量中的派生类对象,并且稍后在程序中,需要检索这些共享指针。

以下代码说明了我的问题:

#include <iostream>
#include <vector>
using namespace std;

#include <boost/make_shared.hpp>
#include <boost/foreach.hpp>

class Base
{
public:
    virtual ~Base()
    {
    }
};
/******************************************/

typedef boost::shared_ptr< Base > BasePtr;
/******************************************/

class Derived1 : public Base
{
public:
    void derived1_test()
    {
        cout << "derived1_test" << endl;
    }
    /******************************************/
    int i1;
};
/******************************************/

typedef boost::shared_ptr< Derived1 > Derived1Ptr;
/******************************************/

class Derived2 : public Base
{
public:
    void derived2_test()
    {
        cout << "derived2_test" << endl;
    }
    /******************************************/
    int i2;
};
/******************************************/

typedef boost::shared_ptr< Derived2 > Derived2Ptr;
/******************************************/

int main()
{
    Derived1Ptr d1 = boost::make_shared< Derived1 >();
    Derived2Ptr d2 = boost::make_shared< Derived2 >();

    vector< BasePtr > v;
    v.push_back( d1 );
    v.push_back( d2 );
    BOOST_FOREACH(BasePtr bPtr, v)
    {
        try
        {
            Derived1& d11 = dynamic_cast< Derived1& >( *bPtr );
            d11.derived1_test();
        }
        catch (const std::bad_cast& e)
        {
            Derived2& d22 = dynamic_cast< Derived2& >( *bPtr );
            d22.derived2_test();
        }
    }
    return 0;
}

在上面的代码中,如果我更改了BOOST_FOREACH中的代码

Derived1& d11 = dynamic_cast< Derived1& >( *bPtr );

Derived1Ptr d11 = dynamic_cast< Derived1Ptr >( bPtr );

,我在VS2010上遇到编译时错误

invalid target type for dynamic_cast target type must be a pointer or reference to a defined class

我的问题是我想使用boost::shared_ptr而不是引用。其次,我正在使用dynamic_cast,当对象引用属于不同类型时会抛出std::bad_cast异常(尝试将其与共享指针一起使用但得到前面提到的编译器错误)。这显然非常缓慢。我希望能够使用更加注重绩效的方法。我在这里寻找的是任何解决方案,而不是使用dynamic_cast和异常处理。

欢迎任何关于代码或设计变更的建议。

4 个答案:

答案 0 :(得分:13)

答案 1 :(得分:7)

你的设计似乎忽略了这一点;最好使用virtual函数来实现多态行为。

#include <iostream>
#include <vector>
using namespace std;

#include <boost/make_shared.hpp>
#include <boost/foreach.hpp>

class Base
{
public:
    virtual ~Base() {}
    virtual void test() = 0;
};
/******************************************/

typedef boost::shared_ptr< Base > BasePtr;
/******************************************/

class Derived1 : public Base
{
public:
    void test()
    {
        cout << "derived1_test" << endl;
    }
    /******************************************/
    int i1;
};

class Derived2 : public Base
{
public:
    void test()
    {
        cout << "derived2_test" << endl;
    }
    /******************************************/
    int i2;
};

int main()
{
    BasePtr d1 = boost::make_shared< Derived1 >();
    BasePtr d2 = boost::make_shared< Derived2 >();

    vector< BasePtr > v;
    v.push_back( d1 );
    v.push_back( d2 );
    BOOST_FOREACH(BasePtr &bPtr, v) // I use a reference here for efficiency.
    {
        bPtr->test();
    }
    return 0;
}

答案 2 :(得分:3)

如果你的矢量拥有这些物体,你最好使用boost::ptr_vector

答案 3 :(得分:1)

您有几种选择:

正确使用继承(和多态)!即在您的派生类中实现的基类中定义纯虚方法(同样,每个派生类型的额外shared_ptr类型也是多余的!)

使用变体类型来保存所有派生类型(如果您具有有限的集合,则非常有用)。那么就不需要动态强制转换,您可以指定访问者来执行您需要的操作。