强类型包装

距离和时长都能用 double 保存,但把 100 米当成 9.58 秒传下去时编译器毫无察觉——它只看到两个 double。强类型包装用轻量结构体给基础值加上领域含义,让“不该混用”变成编译错误。本章沿用语言基础的聚合与值语义,不引入新的语言机制。

包装类型

strong-types.cpp
// 强类型包装示例:用两个包装类型区分距离与时长。
#include <iostream>

struct Meters {
  double value{0};
};

struct Seconds {
  double value{0};
};

int main() {
  Meters distance{100.0};
  Seconds duration{9.58};
  // distance 与 duration 类型不同,互相赋值会被编译器拒绝
  std::cout << "距离: " << distance.value << " 米\n";
  std::cout << "时长: " << duration.value << " 秒\n";
  return 0;
}

取用数值时写出 .value,类型本身挡住了单位混用。这层小小的摩擦就是包装的成本,也是它换来的检查。

包装的边界

普通聚合包装依赖约定:成员公开,Meters{9.58} 仍能凭空构造,杜绝误用需要构造函数与不变量,留待自定义类型章节。取值封闭的领域值(方向、状态、档位)直接用 enum class。

常见错误

用注释区分单位

double distance; // 米 依赖读代码的人记住单位,复制粘贴时约束就丢了,包装让编译器参与检查。

处处拆包取值

计算始终在同类间进行时,逻辑先留在包装类型内部(需要成员函数,留给自定义类型章节),不在调用点反复写 .value。

自测问题

  1. distance = duration; 为什么通不过编译?

    查看答案

    Meters 与 Seconds 是两个独立类型,之间没有定义转换,类型系统因此拦下了单位混用。

  2. 普通 struct 包装能防止的误用与防不了的误用各是什么?

    查看答案

    能防止不同包装类型之间的赋值与传参混用,不能防止凭空构造一个不合理的值。更强的保证需要构造函数与不变量。

本章回顾

你能用轻量包装区分同底层类型的领域值,也知道它的边界。完整示例见 strong-types.cpp。