我在这里找到了一些关于Null对象模式的信息(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;
}
Run Code Online (Sandbox Code Playgroud)
迫使用户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;
};
Run Code Online (Sandbox Code Playgroud)
现在很清楚是否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;
};
Run Code Online (Sandbox Code Playgroud)
这个概念是否有既定的模式或成语?如果没有,是否有任何实施建议?
在实际代码中,有一些具有1个或更多成员的类在某些情况下是可选的.这些类使用支持缺失字段的协议(即可选字段)在套接字上进行序列化.序列化可以跳过可选字段,而不是浪费字节序列化未明确设置的默认构造对象.例如,一个updateFoo(const Foo&)函数.如果仅Foo更新现有实例的子集,则只需要序列化这些字段.
它似乎std::experimental::optional(由@myaut引起我的注意)是我想要使用但我无法访问它.
现在我需要使用一个可以与Visual Studio 2013(2015可能还可以)和g ++ 4.8一起使用的解决方案.
从这个问题(认为赞成它;):
std::experimental::optional源自Boost.Optional库,此实现在 Visual C++ 12.0 中运行良好(尽管略有不同)。可以在此处找到基于N3793提案论文的参考单标头实现。Visual Studio 附带的受支持的 C++11/14/1z 核心和库功能的最新列表可以从Visual C++ 团队博客(特别是这篇文章)中找到。可以在此处查看 Microsoft 标准库实现(和一些扩展)的一组头文件。
我最近尝到了它的滋味,经过一些努力来构建它,我设法使用它并且对它很满意。希望能帮助到你。
| 归档时间: |
|
| 查看次数: |
648 次 |
| 最近记录: |