4

我有课MyObject。它的所有实例都应该由 a 拥有MyObjectSet,并且不能在其他任何地方构造它。在里面MyObjectSet,我使用 astd::vector<MyObject>来存储所有实例。

问题是,std::vector<MyObject>为了工作,移动构造函数必须是公共的(添加为 的朋友MyObject是不够的)。std::vector<MyObject>MyObject

class MyObject {
    MyObject(int n);
    friend class MyObjectSet;
  public:
    MyObject(MyObject&&) = default; // without this, it doesn't compile
};

class MyObjectSet {
    std::vector<MyObject> MyObjects;
  public:
    MyObject& GetMyObject(int some_param);
};

但是,如果我将其公开,则可以MyObject从其他地方实例化。

void SomeUnrelatedFunc(MyObjectSet& set) {
    MyObject m(std::move(set.GetMyObject(0))); // this shouldn't be possible
}

有没有办法解决这个问题?

可以在内部存储指向MyObject实例的指针MyObjectSet,但如果可能的话,我想避免这种情况。

4

2 回答 2

2

您需要声明std::allocator<MyObject>为好友:

class MyObject {

    MyObject(int n);
    friend class MyObjectSet;
    friend std::allocator<MyObject>;
};

然后用于vector::emplace_back()实际构造您的对象。

class MyObjectSet {
    std::vector<MyObject> MyObjects;

public:
    MyObject& GetMyObject(int some_param)
    {
        MyObjects.emplace_back( some_param );
        return MyObjects.back();
    }
};

emplace_back()具有调用 MyObject 构造函数,将 some_param 作为 int 参数传递给构造函数,并将创建的对象插入到列表的后面的效果。构造调用是从 std::allocator 内部完成的,因此需要它的友谊。

于 2013-03-30T20:22:03.550 回答
0

您可以创建一个自定义分配器并将其作为第二个参数传递给您的std::vector<>. 让您的自定义分配器成为 MyObject 的朋友。您的自定义分配器不需要做任何特殊的事情——唯一的目的是以通常的方式(例如使用 new)分配 MyObjects,同时通过成为朋友来访问私有构造函数。

于 2013-03-30T21:38:30.507 回答