2

我需要几个在程序运行时始终可用的独特对象。我遵循 Singleton 设计模式,它建议使用方法getInstance()来获取对象。但我更喜欢立即检索对象而不调用方法。所以我写了一个类,它提供了几个由引用类型而不是指针返回的唯一对象。

class Priority
{
public:
    static Priority &High;
    static Priority &Medium;
    static Priority &Low;

    std::string getName(void);
    int getLevel(void);

private:
   Priority(int level, std::string const& name);
   ~Priority();
   Priority(Priority const&);
   const Priority &operator = (Priority const&);

   int level_;
   std::string name_;
};

Priority &Priority::High   = Priority(3, "High");
Priority &Priority::Medium = Priority(2, "Medium");
Priority &Priority::Low    = Priority(1, "Low");

Priority::Priority(int level, std::string const& name)
   : level_(level), name_(name)
{ }

Priority::~Priority() { }

inline std::string Priority::getName(void)
{
    return name_;
}

inline int Priority::getLevel(void)
{
    return level_;
}


我编写了一个使用上述类的示例程序。

int main()
{
    Priority &m = Priority::High;
    std::string name = m.getName();
    int level = m.getLevel();
    return 0;
}


该程序运行良好。因此,我假设在 Priority &Priority::High = Priority(3, "High");程序停止或存储类的 dll 文件被卸载之前,分配给变量的内存不会被清除。我对么?

4

2 回答 2

1

问题。

您显示的代码不应该编译:您不能将对 non- 的引用绑定const到右值。

Visual C++ 11.0 和 g++ 4.7.1 的示例:

[D:\开发\测试]
> cl foo.cpp
foo.cpp
foo.cpp(27):警告 C4239:使用了非标准扩展:“初始化”:从“优先级”转换为“优先级 &”
        非常量引用只能绑定到左值
foo.cpp(28):警告 C4239:使用了非标准扩展:“初始化”:从“优先级”转换为“优先级 &”
        非常量引用只能绑定到左值
foo.cpp(29):警告 C4239:使用了非标准扩展:“初始化”:从“优先级”转换为“优先级 &”
        非常量引用只能绑定到左值

[D:\开发\测试]
> gnuc foo.cpp
foo.cpp:27:48:错误:从“Priority”类型的右值对“Priority&”类型的非常量引用进行无效初始化
foo.cpp:28:50:错误:从“Priority”类型的右值对“Priority&”类型的非常量引用进行无效初始化
foo.cpp:29:47:错误:从“Priority”类型的右值对“Priority&”类型的非常量引用进行无效初始化

[D:\开发\测试]
> _

工具使用。

在 Visual C++ 中,使用选项/W4(警告级别 4)来获取上面显示的警告。

您可以将这个和其他“使其符合标准”选项放在环境变量中CL(同样,LINK对于 Microsoft 链接器,例如/entry:mainCRTStartup作为默认链接器选项)。

[D:\开发\测试]
>回声 %CL%
/nologo /EHsc /GR /W4 /FI"progrock/cppx/macro/c++11.for_msvc_11.h"

[D:\开发\测试]
> _

C++ 解决了这个问题。

你可以使用右值引用而不是左值引用,但是尽管 Visual C++ 对此很满意,但 g++ 然后抱怨私有析构函数。

因此,除了参考想法——它的目的是什么?– 您可以简单地使用普通的静态数据成员。

但是,对于普通的静态数据成员,与 Meyers 的单例相反,您可能会遇到静态初始化命令 fiasco的风险。因此,如果您绝对必须提供全局变量,我建议为此使用单例。至于那种单例,使用最简单的解决方案通常是最好的,这意味着迈耶斯的单例(我只是链接了第一个看起来合理的谷歌结果)。

于 2012-11-26T13:11:57.330 回答
1

这甚至不应该编译,您正在使用临时对象初始化引用。但是,您根本不需要那里的参考资料;只需将静态成员直接声明为对象:

在标题中:

class Priority
{
public:
    static Priority High;
    static Priority Medium;
    static Priority Low;
//...
};

在源文件中:

Priority Priority::High(3, "High");
Priority Priority::Medium(2, "Medium");
Priority Priority::Low(1, "Low");
于 2012-11-26T13:12:43.383 回答