这是一个Unique
类,用于创建唯一的对象。对象是通过工厂方法Unique::Get
创建的,并通过传递给此方法的值来唯一。该方法检查唯一对象集合Unique::cache
中是否存在带有该值(键)的对象,如果不存在,则创建一个新对象并将其插入到该对象集中。
我希望此类仅对用户有用。具体来说,用户不应通过调用Get
方法来复制此类的对象或创建对象。为此,我将构造函数和赋值运算符声明为私有(private)。但是当我这样做时,我不能在类本身内使用std::set::emplace,因为构造函数是私有(private)的。
可能的解决方案是将std::set
类声明为好友,但这将使用户也可以将此容器与我的类一起使用。这可能是有害的。
有没有更好的办法?
#include <set>
#include <iostream>
#include <iomanip>
class Unique {
public:
// user accessible methods
static const Unique &Get(int key);
bool operator==(const Unique &other) const {
return this == &other;
}
private:
// user inaccessible methods
Unique(int key) : key_(key) {}
Unique(const Unique &) = delete;
Unique &operator=(const Unique &) = delete;
int key_;
private:
// cache related stuff
struct Identity {
Identity(int key) : key_(key) {}
int key_;
};
struct Compare {
struct is_transparent {};
bool operator()(const Identity &lhs, const Unique &rhs) const {
return lhs.key_ < rhs.key_;
}
bool operator()(const Unique &lhs, const Identity &rhs) const {
return lhs.key_ < rhs.key_;
}
bool operator()(const Unique &lhs, const Unique &rhs) const {
return lhs.key_ < rhs.key_;
}
};
static std::set<Unique, Compare> cache;
};
std::set<Unique, Unique::Compare> Unique::cache;
const Unique &Unique::Get(int key) {
Identity identity(key);
auto it = cache.find(identity);
if (it == cache.end()) {
it = cache.emplace(key).first;
}
return *it;
}
int main() {
const Unique &c1 = Unique::Get(1);
const Unique &c2 = Unique::Get(1);
std::cout << std::boolalpha << (c1 == c2) << std::endl;
}
最佳答案
除通过“官方 channel ”外,有几种防止直接构造类实例的常用技术。
这是其中最简单的一个:创建必须使用工厂方法构造的类的示例,但该类具有公共(public)构造函数:
头文件:
class Object {
class private_inner {};
public:
Object(const private_inner &);
static Object factory();
};
您的实现类;
static Object::private_inner inner;
Object Object::factory()
{
return Object(inner);
}
构造函数需要对私有(private)类成员的引用。即使构造函数是公共(public)的,它也不可用,因为私有(private)类成员不可访问。
同时,
factory()
本身没有问题。我确定您可以使该示例适合您的类层次结构。请注意,您的工厂可以毫无问题地在C++库容器中调用
emplace()
,因为您的工厂将拥有对私有(private)类的完全访问权限,并将其传递给容器的方法。