我希望我的Timer对象只能通过Timer :: create()创建。为此,我将构造函数设为私有。但是,我得到一个编译器错误,说“Timer :: Timer(unsigned int)'是私有的”在new_allocator.h的上下文中。我该如何解决这个问题?
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;
答案 0 :(得分:13)
您可能应该实现自己的分配器,它将成为计时器的朋友:
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
并实现自己的{{1}实际创建construct
s。
答案 1 :(得分:11)
您可以使用友元转移语义来避免必须拥有专门的vector
分配器。这有点像依赖注入友谊。这真的很简单。你创建了一个空类,让自己成为你班级的朋友。但默认构造函数是私有的,因此只有您的类可以创建它的实例。但是这个类仍然是可复制的,所以它可以传递给任何人。
您的Timer
构造函数将是公共的,但它需要其中一个对象作为参数。因此,只有您的类或它所调用的函数才能直接创建这些对象(复制/移动仍然有效)。
以下是您在代码(live example)中执行此操作的方法:
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;