gpt4 book ai didi

c++ - 如何实现空对象?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:43:16 27 4
gpt4 key购买 nike

详情

我在这里 ( https://softwareengineering.stackexchange.com/questions/152094/null-pointers-vs-null-object-pattern ) 和这里 ( http://en.wikipedia.org/wiki/Null_Object_pattern#C.2B.2B) 找到了一些关于空对象模式的信息。

但是,C++ 实现并未说明我的用例。

我还看到了可空类型 ( 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;
}

可能的解决方案1

强制需要区分默认状态和unset 之间歧义的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

可能的解决方案2

更新 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 个或多个成员,它们在某些情况下是可选的。这些类正在使用支持缺失字段(即可选字段)的协议(protocol)通过套接字进行序列化。序列化可以跳过可选 字段,而不是浪费字节序列化未显式设置的默认构造对象。例如,updateFoo(const Foo&) 函数。如果只有现有 Foo 实例的一个子集被更新,那么只有那些字段需要被序列化。

编辑

看起来 std::experimental::optional(@myaut 引起了我的注意)是我想要使用的,但我无权访问它。

现在我需要使用适用于 Visual Studio 2013(2015 可能没问题)和 g++ 4.8 的解决方案。

最佳答案

来自 this question (想赞成它;):

std::experimental::optional originates from the Boost.Optional library, and this implementation works well in Visual C++ 12.0 (though it differs a little). Reference single-header implementation, based on the N3793 proposal paper, can be found here.

The latest list of supported C++11/14/1z core and library features that are shipped with Visual Studio can be found from the Visual C++ Team blog, from this post in particular. A set of header files of the Standard Library implementation (and some extensions) from Microsoft can be viewed here.

我最近尝试了一下,为了构建它付出了一些努力,我设法使用了它并且对它很满意。希望对您有所帮助。

关于c++ - 如何实现空对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29460651/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com