我在这里找到了一些关于空对象模式的信息(https://softwareengineering.stackexchange.com/questions/152094/null-pointers-vs-null-object-pattern)和这里(http://en.wikipedia.org/wiki/Null_Object_pattern#C.2B.2B)。
但是,C ++实现并没有说明我的用例。
我还看到了 Nullable Type (http://en.wikipedia.org/wiki/Nullable_type)的相关链接。
我有一个不属于层次结构的对象,通常不会在堆上分配。此外,没有一个方便的值可以用作标记 null 的标记。希望以下代码能够清楚地说明用例。
class ContrivedType
{
public:
ContrivedType() :
mValue(0)
{
// Do nothing
}
bool operator==(const ContrivedType& other) const
{
return mValue == other.mValue;
}
void setValue(std::uint16_t value)
{
mValue = value;
}
private:
// All values in the range [0, 65535] are valid for use
std::uint16_t mValue;
};
class Foo
{
public:
const ContrivedType getValue() const
{
return mValue;
}
void setValue(const ContrivedType &value)
{
mValue = value;
}
private:
ContrivedType mValue;
};
int main()
{
Foo f;
if (f.getValue() == ContrivedType())
{
// Ambiguous case
// - Was this value explicitly set to be the same value
// as when it's default constructed
// OR
// - Was the value never set
}
return 0;
}
强制需要消除默认状态和取消设置之间歧义的ContrivedType
用户使用指针并动态分配ContrivedType
。也许是这样的?
class Foo
{
public:
Foo() :
mValue(nullptr)
{
// Do nothing
}
const ContrivedType* getValue() const
{
return mValue.get();
}
void setValue(const ContrivedType &value)
{
if (!mValue)
{
mValue.reset(new ContrivedType(value));
}
else
{
*mValue = value;
}
}
private:
std::unique_ptr<ContrivedType> mValue;
};
现在很清楚ContrivedType
是否已设定。
更新ContrivedType
的实施以支持 null 的概念。
class ContrivedType
{
public:
ContrivedType() :
mState(nullptr)
{
// Do nothing
}
explicit ContrivedType(std::uint16_t value) :
mState(&mStorage)
{
mStorage.mValue = value;
}
bool isNull() const
{
return mState == nullptr;
}
bool operator==(const ContrivedType& other) const
{
if (!isNull())
{
return mStorage.mValue == other.mStorage.mValue;
}
else
{
return other.isNull();
}
}
void setValue(std::uint16_t value)
{
mStorage.mValue = value;
if (!mState)
{
mState = &mStorage;
}
}
private:
struct State
{
// All values in the range [0, 65535] are valid for use
std::uint16_t mValue;
};
State mStorage;
// This will point to the storage when a value actually set
State* mState;
};
这个概念是否有既定的模式或成语?如果没有任何实施建议?
在实际代码中,在某些上下文中有一些包含1个或更多成员的类 optional 。这些类使用支持缺失字段的协议(即可选字段)在套接字上进行序列化。序列化可以跳过可选字段,而不是浪费字节序列化未明确设置的默认构造对象。例如,updateFoo(const Foo&)
函数。如果仅更新现有Foo
实例的子集,则只需要序列化这些字段。
看起来像std::experimental::optional
(@myaut提请我注意)是我想要使用但我无法访问它。
现在我需要使用一个可以与Visual Studio 2013(2015年可能还可以)和g ++ 4.8一起使用的解决方案。
答案 0 :(得分:2)
从this question开始(想到赞成它):
std::experimental::optional
源自Boost.Optional库,此实现在Visual C ++ 12.0中运行良好(尽管它不同a little)。可以找到基于N3793提案文件的参考单页头实施here。Visual Studio附带的受支持的C ++ 11/14 / 1z核心和库功能的最新列表可以从Visual C++ Team blog,特别是this post中找到。可以查看Microsoft的标准库实现(以及一些扩展)的一组头文件here。
我最近尝到了它的味道,为了构建它我付出了一些努力,我设法使用它,并对它很满意。希望它有所帮助。