25

我希望仅通过 Timer::create() 创建我的 Timer 对象。为此,我将构造函数设为私有。但是,在 new_allocator.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;
4

2 回答 2

15

您可以使用友谊转移语义来避免使用专门的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;
于 2013-06-09T15:24:25.417 回答
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);
}

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

于 2013-06-09T09:22:33.267 回答