3

假设我们有一个单例类,其中的 Instance 函数(返回该类的单例实例的函数)已被重载。一个版本接受一些参数并在类构造函数中初始化对象,另一个版本不接受任何参数。

1.    myClass::Instance ( int x, int y );
2.    myClass::Instance ( );

我们想要实现的是类的用户应该总是首先调用(1),并且任何后续调用都应该只对(2)进行。不应允许用户第一次调用 (2),一旦调用 (1),就不允许对 (1) 进行后续调用。

是否可以在不将检查 NULL 指针的负担放在类的用户身上来实现这一点?

4

3 回答 3

3

问题是你不可能让编译器在编译时仲裁这个“第一次调用”概念(因为它编译一个特定的翻译单元,它不知道是否可以从其他翻译单元调用 (1)) ,所以你必须:

  • 设计以在编译时限制对一个或两个重载的访问,和/或
  • 在运行时检查有效使用情况,和/或
  • 使您的代码更能容忍对 (1) 的多次调用,同时确保您获得所需的行为。

有许多可能的方法可能足够也可能不够:

  • 您可以(1)通过使其受保护或私有来更难访问,同时将友谊授予将调用它的特定代码,而将(2)公开以方便代码的其他部分继续使用

  • 您可以编写 (1) 的代码,以便在第一次忽略任何参数并调用 (2)

  • 您可以在运行时使用断言来验证使用情况,这有望确保客户端代码在投入生产之前很久就符合您的条件

  • 您可以 (1) 返回调用 (2) 所需的内容,例如客户端无法以其他方式创建的类型的对象,但仅此一项并不能阻止 (1) 再次被调用。所需的对象可能会传递给 (2) 的构造函数,或者 (2) 可能成为该对象上的函数。

于 2013-06-26T07:53:23.783 回答
2

1.如果实例已经存在,则抛出异常(例如std::logic_error)。如果不是,则使用提供的参数构造实例并返回它。

在 2. 如果实例尚不存在,则抛出异常(例如 std::logic_error)。然后你退货。

于 2013-06-26T07:50:45.427 回答
0

您可以为此使用 std::call_once ( http://en.cppreference.com/w/cpp/thread/call_once )。您将需要一个 once_flag ( http://en.cppreference.com/w/cpp/thread/once_flag ) 私有成员 (例如 m_once_flag)。

在 1:您将您的实现包装在一个 call_once 周围,并将 m_once_flag 作为第一个参数。

在 2:你打电话给 1。

call_once 将注意该函数仅在第一次执行。

于 2017-12-05T10:48:50.343 回答