函数返回引用,失败时返回什么?

时间:2011-07-14 12:51:04

标签: c++ singleton

由于设计了一个我用插件定位的框架,我已经将我的代码的一部分实现为单例。该类负责处理与我在框架内进行通信的外部程序的连接。

启用外部通信是一种运行时设置,但如果禁用,我不希望允许从框架内的模型访问它。我已经使用这里经常推荐的版本实现了它:

class Communicator {
public: 
    static Communicator& getInstance() {
        static Communicator instance;
        return instance;
    }
    // ...
private: 
    static bool ServiceEnabled;
    // Constructors, operator=, etc ...
}

现在,鉴于ServiceEnabledfalse,我不想让getInstance返回有效的Communicator。但是因为我返回一个引用,我不能简单地返回0或者一些这样的......什么是正确的行为?请注意,即使ServiceEnabled为false,继续执行也是完全有效的,所以我不能只是中止它。

7 个答案:

答案 0 :(得分:4)

添加公共功能

static bool IsServiceEnabled();

并在getInstance中抛出异常,当它在ServiceEnabled == false时调用;

答案 1 :(得分:4)

实际上有很多可能性......这是列表的开头,没有特别的顺序。

<强>指针

class Communicator {
public:
  static Communicator const* Instance(); // returns 0 if not Enabled
};

实际上可以用“更安全”的指针类型代替(如果指针为空且有人试图使用它,则断言/抛出)。

查询+投掷

class Communicator {
public:
  static bool IsEnabled();
  static Communicator const& Instance(); // throw if not Enabled
};

空对象

class Communicator {
public:
  static Communicator const& Instance(); //returns a null instance if not Enabled

  void doit() { if (!enabled) { return; } }
};

我个人不喜欢最后一个,因为隐藏了未启用的事实,您可能会阻止用户及早发现问题。想想一个交易系统,它确信在将所有内容发送到/dev/null ...

时已经注册了它的交易

答案 2 :(得分:1)

正确的行为是在遇到失败时抛出异常:

#include <stdexcept>

class Communicator {
public: 
    static Communicator& getInstance() {
        static Communicator instance;
        if (ServiceEnabled)
          return instance;
        else
          throw std::exception("Get communicator while service is not enabled");
    }
    // ...
private: 
    static bool ServiceEnabled;
    // Constructors, operator=, etc ...
}

答案 3 :(得分:0)

我会再次考虑设计决策,然后可能会创建一个异常类并抛出它。这当然需要在另一端处理可能的异常。

答案 4 :(得分:0)

也许您应该将具有错误ServiceEnabled的传播者视为“有效”

要实现,您需要一个方法bool IsEnabled(),并且您的其他方法需要检查servoce是否已启用,并且最常见的是,如果不是,则立即返回。

答案 5 :(得分:0)

如果没有启用,为什么不让类忽略所有带副作用的调用?这样您就可以调用所需的所有功能,而不必担心它是打开还是关闭。提供“IsServiceEnabled”(作为Henrik答案)以允许用户知道它是否应该进行通信。

答案 6 :(得分:0)

如果您真的希望能够在运行时打开和关闭通信,您可能需要担心用户可以在启用时保存Communicator引用这一事实,并在以后禁用它时尝试使用它。 当然,这个问题并不是单身人士所独有的 你可以引入另一层间接来处理它:

class CommunicatorImpl
{
public:
    virtual bool isEnabled() const = 0;
    virtual void doSomething() = 0;
};

class CommunicatorImpl_Enabled : public CommunicatorImpl
{
    public:
        virtual bool isEnabled() const { return true; }
        virtual void doSomething()  { /* Do something... */}
};


class CommunicatorImpl_Disabled : public CommunicatorImpl
{
    public:
        virtual bool isEnabled() const { return false; }
        virtual void doSomething()  { throw CommunicationIsDisabled("SRY"); }
};



class Communicator {
public: 
    static Communicator& getInstance() {
        static Communicator instance;
        return instance;
    }

    void enable () { m_impl = &m_enabled; }
    void disable () { m_impl = &m_disabled; }
    bool isEnabled() const { return m_impl->isEnabled(); }
    void doSomething() { m_impl->doSomething(); }

private: 
    CommunicatorImpl* m_impl;
    CommunicatorImpl_Enabled m_enabled;
    CommunicatorImpl_Disabled m_disabled;
}