可能重复:
C++中的Nullable值
在C++中表示可空成员的最佳方法是什么?
在C#中,我们可以使用Nullable<T>类型.非常需要这样的数据类型,因为并非所有数据都具有有意义的价值.这是一个非常重要的数据类型,@ Jon Skeet花了整整一章,跨越了27页,仅Nullable<T>在他的优秀着作C#Depth中进行了描述.
一个简单的例子可以是一个Person类1,定义为:
struct Person
{
std::string Name;
DateTime Birth;
DateTime Death;
//...
};
Run Code Online (Sandbox Code Playgroud)
由于一个人总是有生日,所以Birth上述班级的成员总会有一些有意义的价值.但是怎么样Death?如果这个人还活着,它应该有什么价值呢?在C#中,此成员可以声明为Nullable<DataTime>2,null如果此人活着,则可以将其分配.
在C++中,解决这个问题的最佳方法是什么?截至目前,我只考虑了一个解决方案:将成员声明为指针:
DataTime *Death;
Run Code Online (Sandbox Code Playgroud)
现在它的价值可以是nullptr人活着的时候.但它强迫使用new死人,因为它会有一些有效的价值.它反过来意味着不能依赖编译器生成的默认复制语义代码.程序员必须编写复制构造函数,复制赋值,析构函数遵循三条规则(C++ 03),或者在C++ 11中规则,五条规则.
那么,除了制作指针之外,我们还有更好,更优雅的解决方案吗?
其他示例包括关系数据库表,因为在许多DBMS中,列可以为空.
这也有一个简写.人们可以写DataTime?这正是因为相同Nullable<DateTime>.
为什么std::optional(目前std::experimental::optional在libc ++中)没有引用类型的专门化(与之相比boost::optional)?
我认为这将是非常有用的选择.
是否有一些对象引用了STL中可能已存在的对象语义?
我有一个结构Foo.在伪代码中:
def FindFoo:
foo = results of search
foundFoo = true if a valid foo has been found
return foo if foundFoo else someErrorCode
Run Code Online (Sandbox Code Playgroud)
我怎样才能在C++中实现这一目标?
编辑删除了许多不准确之处.
我正在尝试使用c ++ 11功能实现boost :: optional之类的数据结构.这是我到目前为止:
template<typename T>
struct maybe {
bool valid;
union {
T value;
};
maybe() : valid(false) {}
maybe(const T& _v) {
valid = true;
new (&value) T(_v);
}
maybe(const maybe& other) {
if (other.valid) {
valid = true;
new (&value) T(other.value);
}
else valid = false;
}
~maybe() {
if (valid)
value.~T();
}
bool is_valid() { return valid; }
operator T&() {
if (valid) return value;
throw std::bad_exception();
}
};
Run Code Online (Sandbox Code Playgroud)
我利用无限制联合功能为可选值创建一个正确对齐的空间,该空间可以原位存储,而不是动态分配空间.事情主要起作用,除非我想创建一个带引用的<>.例如maybe<int&>导致g ++ 4.7抱怨:
error: …Run Code Online (Sandbox Code Playgroud) 我很难理解stroustrup对于必须遇到什么困难的解释,如果运算符重载'.' 曾经被允许.
请参阅Bjarne Stroustrup的这句话:
运营商.(dot)原则上可以使用与 - >相同的技术重载.但是,这样做会导致对操作是否意味着对象重载的问题.或者提到的对象.例如:
class Y {
public:
void f();
// ...
};
class X { // assume that you can overload .
Y* p;
Y& operator.() { return *p; }
void f();
// ...
};
void g(X& x)
{
x.f(); // X::f or Y::f or error?
}
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,为什么在执行时会有任何混淆x.f() ?
Y& operator.() { return *p; }
Run Code Online (Sandbox Code Playgroud)
这是我的想法:
Y& operator.()( return *p; }不应该被称为obivous和直觉吗?*p指向Y类型的对象,因此Y::f()应该最终调用(不是X::f())我在stroustup的解释中缺少什么?为什么不直截了当?
我在学习C++时正在实现一个国际象棋模块.在我已经(部分)实施的模块中:
Board类(网格,碎片,移动方法等)Colour(黑色/白色)和Rank(KING,QUEEN,...,PAWN)和
Piece分组颜色和等级的结构(BLACK KING,...,WHITE PAWN).我现在正在决定如何在电路板(网格)上表示正方形的内容.一个正方形必须包含一个Piece(黑王),或者什么都不包含.考虑的选项:
创建一个struct Square包含两个数据成员,{bool occupied ; Piece piece;}(可能扩展Piece该类).
我的反对意见:解决方案似乎有点过于沉重,如果广场没有被占用,那么该piece成员应该是空的.我觉得它可能导致某些类方法需要例外,这些方法本来是不必要的.
扩展枚举Rank或Colour包含空选项.
我的反对:感觉语言不优雅,黑客和不自然.
寻找其他类似的包 std::optional
我的反对意见:对于编码风格和简洁性,我想避免使用额外的机器.会std::optional甚至是合适的?
使用NULL或nullptr表示空方格的状态
我的反对意见:再次,看起来很丑陋.空方块的内容不是NULL,也不是数字0,不应该与数字26相当......但应该是一个新的,新的常量EMPTY_SQUARE.
这些选项似乎都不合适.是否有更优雅的方式扩展类(如Piece)与其他成员(如EMPTY_SQUARE)没有原始类的数据成员?(还有其他选择吗?)