2.1 Introduction
用户自定义类型主要包括class和枚举,结构体联合体等等就不说了
2.2 Structures
结构体的简单使用示例
2.3 Classes
数据和方法分开有其好处:可以随意使用数据,但随意代表混乱、容易出错,且不希望所有内部数据都裸露,只希望方便地使用,此时需要把数据和方法捆绑在一起
There is no fundamental difference between a struct and a class; a struct is simply a class with
members public by default.
这里也说到结构体和类的区别,仅仅在成员的默认访问权限上有不同
2.4 Enumerations
The class after the enum specifies that an enumeration is strongly typed and that its enumerators
are scoped. Being separate types, enum classes help prevent accidental misuses of constants
enum Color { red, blue, green };
enum Traffic_light { green, yellow, red };
enum AnotherColor { red, blue, green };报错重定义
// enum class 可以解决这个问题,限定了作用域
Color col = Color::red;
Traffic_light light = Traffic_light::red;
enum class Color { red, blue, green };
enum class Traffic_light { green, yellow, red };
Color col = Color::red;
Traffic_light light = Traffic_light::red;
整数可以初始化枚举,但枚举不能初始化整数除非强制转换
int i = Color::red; // error: Color::red is not an int
Color c = 2; // initialization error: 2 is not a Color
Color x = Color{5}; // OK, but verbose
Color y {6}; // also OK
int x = int(Color::red);
枚举默认只支持初始化、赋值、==、<这些操作,但我们可以自定义补充:
enum class Color { red, blue, green };
enum class Traffic_light { green, yellow, red };
Color col = Color::red;
Traffic_light light = Traffic_light::red;
Traffic_light& operator++(Traffic_light& t) // prefix increment: ++
{
using enum Traffic_light; // here, we are using Traffic_light
switch (t) {
case green: return t = yellow;
case yellow: return t = red;
case red: return t = green;
}
}
int main() {
enum Color { red, green, blue };//C中枚举,内部作用域和枚举类型相同
int col = green;//使用不需要加Color::
}
2.5 Unions
enum class Type { ptr, num }; // a Type can hold values ptr and num (§2.4)
struct Entry {
string name; // string is a standard-library type
Type t;
double* p; // use p if t==Type::ptr
int i; // use i if t==Type::num
};
void f(Entry* pe) {
if (pe->t == Type::num)
cout << pe->i;
// ...
}
可以看到p和i两块内存是永远无法同时使用的,不如写成联合体:
union Value {
double* p;
int i;
};
struct Entry {
string name;
Type t;
Value v; // use v.p if t==Type::ptr; use v.i if t==Type::num
};
void f(Entry* pe) {
if (pe->t == Type::num)
cout << pe->v.i;
// ...
}
标准库使用variant类型替代了联合体:
struct Entry {
string name;
variant<double*, int> v;
};
void f(Entry* pe) {
if (holds_alternative<int>(pe->v)) // does *pe hold an int? (see §15.4.1)
cout << get<int>(pe->v); // get the int
// ...
}