拥有多态对象集合的首选C ++习惯用法是什么? [英] What's the preferred C++ idiom to own a collection of polymorphic objects?

查看:78
本文介绍了拥有多态对象集合的首选C ++习惯用法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下课程

class Base {
public:
    virtual void do_stuff() = 0;
};

class Derived : public Base {
public
    virtual void do_stuff() { std::cout << "I'm useful"; };
};

现在让我们说我想让另一个类负责拥有Base派生类型的对象,并通过调用它们的do_stuff()方法遍历它们.看起来像这样,但是我不知道T应该声明为

Now let's say I want to have another class responsible for owning objects of Base's derived types and iterate through them calling their do_stuff() method. It looks like this, but I don't know what T should be declared as

class Owner {
public:
    void do_all_stuff() {
        //iterate through all items and call do_stuff() on them
    }

    void add_item(T item) {
        items.push_back(item);
    }

    vector<T> items;
}

我看到了几种可能性:

T不能为Base,因为我只能添加具体类型为Base的对象,所以这是不可能的.

T can't be Base, since I would only be able to add objects of concrete type Base, so that's out of the question.

T可以是Base*Base&,但是现在我需要信任add_item()的调用者,以便向我传递指向从我从.我不能delete的析构函数中的元素,因为我不知道它们是动态分配的.但是,如果有,应该delete,这使我的模棱两可.

T can be Base* or Base&, but now I need to trust the caller of add_item() to pass me a pointer or a reference to an object that will still exist when I retrieve it from items. I can't delete the elements in Owner's destructor, since I don't know that they were dynamically allocated. However, they should be delete'd if they were, which leaves me with ambiguous ownership.

T可以是Base*Base&,我在Owner中添加了Base* create_item<DerivedT>() { return new DerivedT; }方法.这样,我知道指针将保持有效并由我拥有,但是我无法在DerivedT上调用非默认构造函数.同样,Owner也负责实例化对象.我也必须删除Owner的析构函数中的每个项目,尽管这不是什么大问题.

T can be Base* or Base& and I add a Base* create_item<DerivedT>() { return new DerivedT; } method to Owner. This way, I know the pointer will remain valid and I own it, but I'm unable to call a non-default constructor on DerivedT. Also, Owner becomes responsible for instantiating objects as well. I also have to delete every item in Owner's destructor, although that's not much of an issue.

基本上,我希望能够执行以下操作:

Basically, I'd like to be able to do something similar to:

Owner owner;

void add_one() {
    Derived d;

    owner.add_item(d);
}

void ready() {
    owner.do_all_stuff();
}

void main() {
    for(int i = 0; i < 10; ++i) {
        add_one();
    }
    ready();
}

我确定其中有一些与移动语义有关的东西(我可以移动传递给add_items()的对象以拥有它们),但是我仍然不知道如何声明我的集合.

I'm sure there's something related to move semantics in there (I could move the objects passed to add_items() to own them) but I still can't figure out how my collection would be declared.

这种多态所有权(尤其是STL容器)的C ++习惯用法是什么?

What is the C++ idiom for this sort of polymorphic ownership (particularly with STL containers)?

推荐答案

多态对象必须通过指针或引用来处理.由于它们的生命周期可能不受特定范围的约束,因此它们也可能具有动态存储持续时间,这意味着您应该使用智能指针.

Polymorphic objects have to be handled by pointer or reference. Since their lifetime is probably not bound to a particular scope they will also probably have dynamic storage duration, which means you should use a smart pointer.

std::shared_ptrstd::unique_ptr之类的智能指针在标准集合类型中可以正常工作.

Smart pointers such as std::shared_ptr and std::unique_ptr work just fine in the standard collection types.

std::vector<std::unique_ptr<Base>>

Owner中使用它的方式如下:

Using this in Owner looks like:

class Owner {
public:
    void do_all_stuff() {
        //iterate through all items and call do_stuff() on them
    }

    void add_item(std::unique_ptr<Base> item) {
        items.push_back(std::move(item));
    }

    vector<std::unique_ptr<Base>> items;
}

add_item的参数类型标识添加项目所需的所有权策略,并且要求用户不遗余力地将其搞砸.例如,由于unique_ptr具有显式构造函数,因此它们不能偶然传递具有某些隐式,不兼容的所有权语义的原始指针.

The argument type to add_item identifies the ownership policy required for adding an item, and requires the user to go out of their way to screw it up. For example they can't accidentally pass a raw pointer with some implicit, incompatible ownership semantics because unique_ptr has an explicit constructor.

unique_ptr也将负责删除Owner拥有的对象.尽管您确实需要确保Base具有虚拟析构函数.使用当前定义,您将获得未定义的行为.多态对象应该几乎总是具有虚拟析构函数.

unique_ptr will also take care of deleting the objects owned by Owner. Although you do need to ensure that Base has a virtual destructor. With your current definition you will get undefined behavior. Polymorphic objects should pretty much always have a virtual destructor.

这篇关于拥有多态对象集合的首选C ++习惯用法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆