Chapter 2 User-Defined Types – A Tour of C++

2.3 Classes

struct与class没有根本上的差别;我们可以认为struct是class的简略版本,其中的成员变量,默认都是public。在struct中,我们也能够定义构造函数,析构函数以及成员函数。

2.4 Unions

我们可以将union作为struct,只不过union中的所有成员都会分配在同一个地址,也就是说,union所占用的空间就是其最大的成员所占的空间。一般来说,在同一时刻,一个union只能拥有其中的一个成员。假设,有一个符号表,其中的每一个成员都有一个名字以及一个值。而每一个值既可以是Node*也可以是int:

enum Type { ptr, num }; // 表示值的类型

struct Entry
{
    string name;
    Type t;
    Node* p;
    int i;
};

void f(Entry* pe)
{
    if(pe->t == num)
        cout<< pe->i;
    // ...
}

很明显,成员变量p与i并不会同时使用,所以我们使用struct作为Entry的类型就会造成空间的浪费。此时,我们就可以使用union:

union Value
{
    Node* p;
    int i;
};

struct Entry
{
    string name;
    Type t;
    Value v; // t为ptr,那么我们使用v,反之则使用i。
}

但是上述代码中,我们必须要维护Type中的变量与union中的成员变量的一一对应的关系,这显然很容易造成错误。因此,一般来说,我们会将union以及其对应的Type封装在一个class中。在实践中,我们也建议大家尽可能减少“裸露”union的使用。在c++的标准库中,variant能够很方便的用于替代union类型,且使用的安全性更高。

struct Entry
{
    string name;
    variant<Node*, int> v;
};

void f(Entry* pe)
{
    if(holds_alternative<int>(pe->v))
        cout << get<int>(pe->v);
}

2.5 Enumerations

enum class Color { red, blue, green };
enum class Traffic_light { green, yellow, red };

Color col = Color::red;
Traffic_light light = Traffic_light::red;

上述代码中enum后面的class表示,该枚举类型是强类型。这从一定程度上能够避免枚举之间的混淆:

Color x = red; // error!!! 哪一个red?
Color y = Traffic_light::red; // error!!! 不属于Traffic_light
Color z = Color::red; // 运行ok

int i = Color::red; // error!!! Color::red并不是int
Color c = 2; // error!!! 2并不是Color类型

Color x = Color{5}; // 运行ok,但是有点冗长
Color y {6}; // 运行ok

默认情况下,enum class只有赋值,初始化与比较运算。但是,我们可以定义其运算符,例如:

Traffic_light& operator++(Traffic_light& t)
{
    switch(t)
    {
    case Traffic_light::green:
        return t = Traffic_light::yellow;
    case Traffic_light::yellow:
        return t = Traffic_light::red;
    case Traffic_light::red:
        return t = Traffic_light::green;
    }
}

Traffic_light next = ++light;

2.6 Advice

[06] 避免“裸露”的union,将其与相对应的type封装在class中。

[08] 使用class enum而不是单纯的enum以避免隐式转换。

[09] 为枚举类型定义运算符,使其更便于使用也更安全。

留下评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据