概述
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类型参数的函数。
- (很难做到很好) 寻找使用太多基本类型参数的函数
最后
以上就是传统苗条为你收集整理的判断void*参数类型_C++核心指南(12) I.4: 使接口精确且强类型I.4: 使接口精确且强类型的全部内容,希望文章能够帮你解决判断void*参数类型_C++核心指南(12) I.4: 使接口精确且强类型I.4: 使接口精确且强类型所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复