vector :: emplace_back用于具有私有构造函数的对象

A.B*_*.B. 20 c++ constructor c++11

我希望我的Timer对象只能通过Timer :: create()创建.为此,我将构造函数设为私有.但是,我得到一个编译器错误,说"在新的all_atoroc.h的上下文中,"Timer :: Timer(unsigned int)'是私有的".我怎么解决这个问题?

class Timer {
    private:
        int timeLeft;
        Timer(unsigned int ms) : timeLeft(ms) {}

    public:
        static std::vector<Timer> instances;
        static void create(unsigned int ms) {
            instances.emplace_back(ms);
        }
};

std::vector<Timer> Timer::instances;
Run Code Online (Sandbox Code Playgroud)

Lol*_*4t0 14

您可能应该实现自己的分配器,这将是计时器的朋友:

class Timer {

    struct TimerAllocator: std::allocator<Timer>
    {
        template< class U, class... Args >
        void construct( U* p, Args&&... args )
        {
            ::new((void *)p) U(std::forward<Args>(args)...);
        }

        template< class U > struct rebind { typedef TimerAllocator other; };

    };
    friend class TimerAllocator;

    private:
        int timeLeft;

    Timer(unsigned int ms) : timeLeft(ms) 
    {}

    public:
        static std::vector<Timer, TimerAllocator> instances;
        static void create(unsigned int ms) {
            instances.emplace_back(ms);
        }
};

std::vector<Timer, Timer::TimerAllocator> Timer::instances;

int main()

{
    Timer::create(100);
}
Run Code Online (Sandbox Code Playgroud)

最简单的解决方案是从std::allocator<Timer>重新实现重新rebind绑定到自身,因此vector无法重新绑定分配器std::allocator并实现自己construct实际创建Timers.

  • @KonradRudolph,这并不是那么简单:当然,我建议制作矢量朋友,如果它有效,但事情就是那个矢量_不会调用构造函数,分配器就是_.制作矢量朋友也无济于事. (6认同)
  • 为什么不让所有`std :: allocator <T>`成为朋友?这样,重新绑定无关紧要. (4认同)
  • @leemes,因为没有保证,`std :: allocator <Timer>`将创建Timer _itself_并且不会被重新绑定(或不会委托构造)到其他分配器.实际上,在我的`gcc 4.7.0`中,_does_被重新绑定,所以使它成为frined并没有帮助. (3认同)
  • 为什么不简单地使用`friend class std::allocator&lt;Timer&gt;;`? (2认同)

Nic*_*las 12

您可以使用友元转移语义来避免必须具有专门的vector分配器.这有点像依赖注入友谊.这真的很简单.你创建了一个空类,让自己成为你班级的朋友.但默认构造函数是私有的,因此只有您的类可以创建它的实例.但是这个类仍然是可复制的,所以它可以传递给任何人.

您的Timer构造函数将是公共的,但它需要其中一个对象作为参数.因此,只有您的类或它所调用的函数才能直接创建这些对象(复制/移动仍然有效).

以下是您在代码中执行此操作的方法(实例):

class TimerFriend
{
public:
  TimerFriend(const TimerFriend&) = default;
  TimerFriend& operator =(const TimerFriend&) = default;

private:
  TimerFriend() {}

  friend class Timer;
}

class Timer {
    private:
        int timeLeft;

    public:
        Timer(unsigned int ms, const TimerFriend&) : timeLeft(ms) {}

        static std::vector<Timer> instances;
        static void create(unsigned int ms) {
            instances.emplace_back(ms, TimerFriend());
        }
};

std::vector<Timer> Timer::instances;
Run Code Online (Sandbox Code Playgroud)