千家信息网

C++接口类型怎么定义

发表于:2024-11-20 作者:千家信息网编辑
千家信息网最后更新 2024年11月20日,本篇内容介绍了"C++接口类型怎么定义"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!I.4 Make
千家信息网最后更新 2024年11月20日C++接口类型怎么定义

本篇内容介绍了"C++接口类型怎么定义"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

I.4 Make interfaces precisely and strongly typed(接口类型应该精准且严格)

Reason(原因)

类型是最简单、最好的文档。经过良好定义的类型可以提高易读性,也可以在编译时被检查。同时,类型明确定义的代码通常也会被优化得更好。

Example, don't(反面示例)

Consider:(考虑以下代码)

void pass(void* data);    // weak and under qualified type void* is suspicious

调用者无法确定函数可以接受何种类型和数据是否可能被修改(由于没有用const修饰)。注意所有的指针类型都可以隐式转换为void*,因此调用者很容易(随便)提供一个值。

被调用者必须(通过默契)将数据静态转换为未经验证的类型以便使用它。这样的代码易错且冗长。

只有在传递设计上C++无法描述的数据时才可以使用const void* 。否则考虑使用variant或者指向基础类型的指针作为代替手段。

可选项:模板参数经常可以消除void*而使用T*或者T&。对于一般的代码,这里的T可以是普遍的或者概念约束的模板参数。

译者注:concept是C++20已经决定引入的新概念。

Example, bad(反面示例)

Consider:考虑以下代码:

draw_rect(100, 200, 100, 500); // what do the numbers specify?draw_rect(p.x, p.y, 10, 20); // what units are 10 and 20 in?

调用者在描述一个矩形这一点是明确的,但却不知道具体描述的是那些方面(四角坐标还是边长)。同时,整形数据可以携带任意形式的信息,单位也存在很多可能,因此我们必须猜测四个整形参数的含义。前两个很有可能是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}); // two cornersdraw_rectangle(p, Size{10, 20}); // one corner and a (height, width) pair

显然,我们无法通过静态类型系统捕捉所有错误(例如,认为第一个参数是左上角这个事实就是一种惯例(命名和注释))Example, bad(反面示例)

Consider:(考虑以下代码)

set_settings(true, false, 42); // what do the numbers specify?

参数的类型和值没有说明哪种设定将会被修改,也没有说明值的含义。

This design is more explicit, safe and legible:

下面的设计更清晰、安全和可读。

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

For the case of a set of boolean values consider using a flags enum; a pattern that expresses a set of boolean values.

对于成组使用布尔值的情况,考虑使用枚举类型;下面的模式可以表示一套布尔值。

enable_lamp_options(lamp_option::on | lamp_option::animate_state_transitions);
Example, bad(反面示例)

In the following example, it is not clear from the interface what time_to_blink means: Seconds? Milliseconds?

在下面的例子中,接口没有明确time_to_blink的含义:单位是秒还是毫秒?

void blink_led(int time_to_blink) // bad -- the unit is ambiguous{    // ...    // do something with time_to_blink    // ...}
void use(){ blink_led(2);}
Example, good(范例)

std::chrono::duration类型(C++11)可以让时间间隔的单位更明确。

void blink_led(milliseconds time_to_blink) // good -- the unit is explicit{    // ...    // do something with time_to_blink    // ...}
void use(){ blink_led(1500ms);}

这个函数可以如下设计以便接受任何单位的时间间隔。

templatevoid blink_led(duration time_to_blink) // good -- accepts any unit{    // assuming that millisecond is the smallest relevant unit    auto milliseconds_to_blink = duration_cast(time_to_blink);    // ...    // do something with milliseconds_to_blink    // ...}
void use(){ blink_led(2s); blink_led(1500ms);}

Enforcement(实施建议)

  • (Simple) Report the use of void* as a parameter or return type.

    (简单)报告使用void*作为参数或返回值的情况。

  • (Simple) Report the use of more than one bool parameter.

    (简单)报告以多个布尔值为参数的情况。

  • (Hard to do well) Look for functions that use too many primitive type arguments.

    (很难做好)找到使用太多原始类型参数的函数。

"C++接口类型怎么定义"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

0