C++独特的物品

发布于 2024-10-27 00:53:27 字数 1117 浏览 4 评论 0原文

我想创建一个类,其中可能的实例范围是有限的,并且用户无法创建新实例。例如,货币是唯一的,我正在工作的图书馆的用户不应该能够创建新货币或复制现有货币。我猜这有点像多吨的模式。到目前为止我所知道的是:

#include <string>
#include <boost/smart_ptr/shared_ptr.hpp>

struct Currency {
public:
    typedef const Currency * Pointer;

    std::string code;

    static const Currency & Get(const std::string & Code);
private:
    Currency();
    Currency(const std::string & c);
};

Currency::Currency(const std::string & c)
:code(c) {}

const Currency & Currency::Get(const std::string & Code) {
    typedef boost::shared_ptr<Currency> Value;
    typedef std::map<std::string, Value> MapType;
    static std::map<std::string, Value> map_;

    if (map_.empty()) {
        // Initialize your map here, from a database query or what have you...
    }
    MapType::const_iterator it = map_.find(Code);
    if (it == map_.end()) {
        throw std::exception(("[Currency::Get] Currency '" + Code + "' not found").c_str());
    }
    return *it->second;
}

这个设计有什么明显的问题吗? (我知道这不是线程安全的) 是否有一种我不知道的普遍接受的技术/模式传统上用于实现此目的?

谢谢, 马克.

I would like to create a class where the possible universe of instances is limited, and of which users cannot create new instances. For example, currencies are unique, and users of the library I am working should not be able to create new currencies, or copy existing ones. It is kind of like a multiple-ton pattern, I guess. What I have so far is:

#include <string>
#include <boost/smart_ptr/shared_ptr.hpp>

struct Currency {
public:
    typedef const Currency * Pointer;

    std::string code;

    static const Currency & Get(const std::string & Code);
private:
    Currency();
    Currency(const std::string & c);
};

Currency::Currency(const std::string & c)
:code(c) {}

const Currency & Currency::Get(const std::string & Code) {
    typedef boost::shared_ptr<Currency> Value;
    typedef std::map<std::string, Value> MapType;
    static std::map<std::string, Value> map_;

    if (map_.empty()) {
        // Initialize your map here, from a database query or what have you...
    }
    MapType::const_iterator it = map_.find(Code);
    if (it == map_.end()) {
        throw std::exception(("[Currency::Get] Currency '" + Code + "' not found").c_str());
    }
    return *it->second;
}

Are there any obvious problems with this design? (I know that this isn't thread-safe)
Is there a generally accepted technique/pattern that I am not aware of that is traditionally used to achieve this?

Thanks,
Marc.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

哥,最终变帅啦 2024-11-03 00:53:28

声明一个私有复制构造函数 Currency::Currency(constCurrency&),但不定义它。这可以防止用另一个 Currency 对象初始化一个 Currency 对象。同样,声明一个私有赋值运算符 Currency&货币::运算符=(const 货币&)。这样您就可以防止将一种货币分配给另一种货币。

Declare a private copy constructor Currency::Currency(const Currency&), but don't define it. This prevents initialising a Currency object with another Currency object. Similarly, declare a private assignement operator Currency& Currency::operator=(const Currency&). That way you prevent assigning one currency to another currency.

宁愿没拥抱 2024-11-03 00:53:28

我相信你所说的是单例模式。所以你可以阅读一下。

在大多数语言中获得单例的方法是

1) 将构造函数设为私有

2) 在类内部实例化类的单个实例(单例)(私有静态)

3) 创建一个静态(类)方法,该方法返回指向在步骤 #2 中创建的静态私有实例的指针(通常称为 getInstance() 或 instance() 或类似的东西。)

任何需要使用此单例的人都可以调用

MyClass foo = MyClass::getInstance();
foo.doWork( blah blah );

并使用该单例来完成他们的工作。

根据定义(我认为),单例并不是线程安全的,您注意到这一点是正确的。添加线程安全是一个单独的问题。

看起来您的解决方案已经完成了大部分工作。

What you're talking about, I believe, is the Singleton pattern. So you can read up on that.

The way in most languages to get a singleton is to

1) make your constructors private

2) instantiate a single instance (the singleton) of your class internal to the class (private static)

3) create a static (class) method that returns a pointer to the static private instance created in step #2 (typically called getInstance() or instance() or something like that.)

Anyone needing to use this singleton then calls

MyClass foo = MyClass::getInstance();
foo.doWork( blah blah );

and uses the singleton for their work.

Singletons aren't by definition (I think) thread safe, and you're right to notice that. Adding thread safety is a separate issue.

Looks like you were most of the way there with your solution.

怼怹恏 2024-11-03 00:53:28

您已经拥有了所需的一切!

编辑:

只需修改抛出异常的部分:

if (it == map_.end()) {

    if ( -- part of allowed set -- ){
       -- create a new currency --
    }
    else {
       throw std::exception(("[Currency::Get] Currency '" + Code + "' not found").c_str());
    }
}

您可以通过多种方式进行比较以查看该货币是否被允许:

  1. 另一张地图,列出允许的字符串代码
  2. 关于正则表达式的比较代码
  3. 根据允许值的静态数组手动检查代码

EDIT2:
下面是与上面的答案完全不同的答案:

从问题的描述来看,您实际上可能需要考虑使用枚举而不是类来区分可能的货币类型。

enum Currency { US, CAN, JPY, CHF, EURO };

std::map<Currency curreny, std:string code>;

编辑3:

添加如下内容:

private:
    std::vector<Currency> initializedList;

在 Get 方法中,返回对向量中对象的引用,而不是返回“it->second”。如果尚不存在,请首先将该对象填充到向量中。

You already have everything you need!

EDIT:

Just modify the part where you throw your exception:

if (it == map_.end()) {

    if ( -- part of allowed set -- ){
       -- create a new currency --
    }
    else {
       throw std::exception(("[Currency::Get] Currency '" + Code + "' not found").c_str());
    }
}

You can do your comparison to see if the currency is allowed in a variety of ways:

  1. Another map, listing allowed String codes
  2. A regular expression comparison on the code
  3. Manually checking the code against a static array of allowed values

EDIT2:
Below is a completely separate answer from the one above:

From the description of your problem, you might actually want to consider using enums rather than classes to differentiate between the possible currency types.

enum Currency { US, CAN, JPY, CHF, EURO };

std::map<Currency curreny, std:string code>;

EDIT 3:

Add something like:

private:
    std::vector<Currency> initializedList;

And in your Get method, rather than return "it->second", return a reference to an object in the vector. If it doesn't yet exist, first populate the object into the vector.

病女 2024-11-03 00:53:27

Look into boost:noncopyable to prevent copying; that's a good reference solution that you can both trust and learn from. Preventing instantiation is easy: a private constructor.

江城子 2024-11-03 00:53:27

我不完全确定你想要做什么,但是当然有单例模式,如果你想将实例的数量限制为 1 或者如果你想控制实例的创建方式,你可以使用工厂模式。

I am not fully sure, what you want to do, but of course there is the singleton pattern, if you want to limit the number of instances to 1 or if you want to control how the instances are created you could use the factory pattern.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文