判断void*参数类型_C++核心指南(12) I.4: 使接口精确且强类型

4242394d84d55810286a36c8d0463980.png

I.4: 使接口精确且强类型

Reason

类型是最简单和最好的文档,其明确的含义提高了可读性,亦可在编译时进行检查。此外,精确类型的代码通常优化得更好。

示例, 不要这样用

Consider:

 void pass(void* data); // 弱类型和未限定的void*是可疑的

调用者不确定什么类型是允许的,由于const没有指定,所以也不确定data是否可变。注意,所有的指针类型都可以被隐藏转换成void*,所以调用者很容易提供这个值(译注:太过随意)。

被调用者必须要static_cast到未确认的类型来使用data(译注:通常不能直接操作void*类型),这是易于出错且啰唆的。

在C++中仅仅使用const void*来传递数据也是难以捉摸的,考虑使用variant或者指针基类的指针。

可先方案: 通常,模板参数可以通过将其转换成T*或T&来消除void*,在泛型代码中T可以通用或概念受限的模板参数。

糟糕的示例

考虑:

 draw_rect(100, 200, 100, 500); // 这些数字指什么? draw_rect(p.x, p.y, 10, 20); // 10和20的单位是什么?

很明显,调用者正在描述一个矩形,但它们关联的部分并不明显,并且int可以携带任意形式的信息,包括许多单位的值,所以我们需要猜测4个int的含义,前面两个很有可能是x和y坐标,但后面两个是什么呢?

虽然注释和参数名字是有帮助的,但是我们可以显示地这样声明:

 void draw_rectangle(Point top_left, Point bottom_right); void draw_rectangle(Point top_left, Size height_width); draw_rectangle(p, Point{10, 20}); // 两个角落(译注:左上,右下) draw_rectangle(p, Size{10, 20}); // 一个角落和一个(height, width)对

显然,我们无法使用静态类型系统来捕获所有的错误(例如,按照惯例(名称和注释)左上角应是第一个参数)。

糟糕的例子

考虑如下:

 set_settings(true, false, 42); //数字指什么?

参数类型及其值没有表达出正在指定的设置或这些值的含义。

(下面)这个设计更加显示、安全且易读:

 alarm_settings s{}; s.enabled = true; s.displayMode = alarm_settings::mode::spinning_light; s.frequency = alarm_settings::every_10_seconds; set_settings(s);

考虑使用枚举(enum)来表示一组布尔值(boolean),这是表示一组布尔值的模式。

nable_lamp_options(lamp_option::on | lamp_option::animate_state_transitions);

糟糕的示例

这下面这个示例中,time_to_blink的含义不并能直观地从接口中看出,秒?毫秒?

 void blink_led(int time_to_blink) // 差 -- 单位是有歧义的 { // ... // 使用time_to_blink做一些事 // ... } void use() { blink_led(2); }

好的示例

std::chrono::duration(C++11)有助于显示表达连续时间的单位。

 void blink_led(milliseconds time_to_blink) // 好 -- 单位明确 { // ... // 使用time_to_blink做一些事 // ... } void use() { blink_led(1500ms); }

该函数也可以这样写来接收任意的时间单位:

 template void blink_led(duration time_to_blink) // 好 -- 接收任意单位 { // 假定毫秒是相关的最小单位 auto milliseconds_to_blink = duration_cast(time_to_blink); // ... // 使用milliseconds_to_blink来做事 // ... } void use() { blink_led(2s); blink_led(1500ms); }

强制执行

  • (简单) 报告所有使用void*作为参数或返回值的函数。
  • (简单) 报告不止一个bool类型参数的函数。
  • (很难做到很好) 寻找使用太多基本类型参数的函数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值