函数返回引用,失败时返回什么
Function returning reference, what to return on failure?
作为我用插件瞄准的框架设计的结果,我已经将我的一部分代码实现为单例。这个类负责处理与外部程序的连接,我与外部程序在框架内进行通信。
启用外部通信是一个运行时设置,然而,如果它被禁用,我不想允许从框架内的模型访问它。我使用这里经常推荐的版本来实现它:
class Communicator {
public:
static Communicator& getInstance() {
static Communicator instance;
return instance;
}
// ...
private:
static bool ServiceEnabled;
// Constructors, operator=, etc ...
}
现在,假设ServiceEnabled
是false
,我不想让getInstance
返回一个有效的Communicator
。但是由于我返回一个引用,我不能简单地返回0或诸如此类的…什么是正确的行为?请注意,即使ServiceEnabled
为假,继续执行也是完全有效的,所以如果它为假,我就不能中止。
添加一个公共函数
static bool IsServiceEnabled();
并在getInstance
中抛出异常,当ServiceEnabled == false;
实际上,有很多可能性…这是一个列表的开头,没有特别的顺序。
<<p> 指针/strong>class Communicator {
public:
static Communicator const* Instance(); // returns 0 if not Enabled
};
这实际上可以被一个"更安全"的指针类型所取代(如果指针为空并且有人试图使用它,则断言/抛出)。
Query + Throw
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
时,确信它已经注册了它的事务…
正确的行为是在遇到故障时抛出异常:
#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 ...
}
我会再次考虑设计决策,然后可能会创建一个异常类并抛出它。这当然需要处理另一端可能出现的异常。
也许您应该考虑ServiceEnabled为false的通信器为" valid "
要实现,你需要一个方法bool IsEnabled()
,你的其他方法需要检查服务是否被启用,大多数情况下,如果没有,立即返回。
如果没有启用,为什么不让类忽略所有有副作用的调用?这样你就可以调用你想要的所有函数,而不必担心它是打开还是关闭。提供一个"IsServiceEnabled"(作为Henrik的回答)来允许用户知道它是否应该进行通信。
如果您真的希望能够在运行时打开和关闭通信,您可能需要担心这样一个事实,即用户可以在启用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;
}
- 查找不存在的键时,unordered_map返回什么
- 如果我在 const 函数上使用指针,我可以返回什么?
- 使用枚举作为条件,if 条件将返回什么,真或假?
- 我应该返回什么而不是标准::shared_ptr<>&?
- 当你只使用 return 时,函数返回什么类型;在 c++ 中
- 在C++中,运算符 sizeof 返回什么数据类型?
- ActorItr 迭代器变量中有什么,* ActorItr 返回什么?
- mxGetPr 返回什么?
- 重载运算符返回什么类型的值(对于用户定义的类型):右值还是左值?
- 代码是否有效.如果我想显示第一个元素?如果不是,那么 s.begin() 会返回什么?
- 范围分辨率运算符在类型:: var的情况下返回什么
- fork_rv返回什么
- int* foo(int a)在C 中返回什么
- 当找不到请求的注册表值时,ReggetValue会返回什么
- 我们应该在带有 char *func(char *string) 的函数中返回什么?需要简要说明这与 c 中的 char
- 重载的 QAbstractItemModel::flags 应该为无效的 QModelIndex 返回什么
- 试图在每次输出后使用一个函数摆脱'0',但不确定我可以返回什么
- 查找函数在失败结果中应该返回什么
- 当c 中的矢量容器过载[]运算符时,我对未定义的索引返回什么
- 新运营商在组装中返回什么