条款18:让接口容易被正确使用,不易被误用

程序设计中经常遇到的便是如何设计接口,让用户能够直观的、快速的了解并上手使用接口。让接口容易被正确使用,不易被误用便是本条款所强调的。
理想上,如果客户企图使用某个接口而却没有获得他所预期的行为,这个代码不应该通过编译;如果代码通过了编译,他的作为就该是客户所想要的。

比如这样一个表示时间的类:

class Date {
public:
    Date(int month, int day, int year);
};

如果我们不对接口做一些“强制性“的约束,该接口就可能被误用:

Date date(2022, 2, 25);	//传参顺序不对
Date date(31, -1, 0);	//参数非法

虽然上述调用可以通过编译,但却可能与用户意图违背。为此我们可以采用类型系统:

class Month {
public:
    explicit Month(int m) : month(m) {

    }
private:
    int month;
};

class Day {
public:
    explicit Day(int d) : day(d) {

    }
private:
    int day;
};

class Year {
public:
    explicit Year(int y) : year(y) {

    }
private:
    int year;
};

class Date {
public:
    Date(const Month &m, const Day &d, const Year &y);
};

这时,我们对用户使用该类的方式做了一些约束,比如:

Date date(2022, 2, 25);				//报错,explicit禁止隐式类型转换
Date date(Day(25), Month(2), Year(2022));//报错,传参顺序不对
Date date(Month(2), Day(25), Year(2022));//正确

虽然我们对传参的顺序,方式做了一定的约束,但是还是避免不了传入非法值,比如:

Date date(Month(22), Day(25), Year(2022));

月份为22显然不合法。为此,我们可以预先定义所有有效的值(即告知用户,只能使用这几个值哦):

class Month {
public:
    static Month Jan() { return Month(1); }
    static Month Feb() { return Month(2); }
    //...
private:
    explicit Month(int m);
};

再使用时,只能这样,这样总不会写错了吧?:

Date date(Month::Jan(), Day(25), Year(2022));

预防用户错误的另一个做法是,限制类型内什么事可做,什么事不可做。常见的限制是加上const。
比如:我们重载了*并且返回值被const限定,当用户一不小心将==写成=时,程序可以告知用户,唉?你这里是不是要做比较?而不是赋值??

if (a * b = c) // ? 

后面部分理解不是很透彻,再续。
关于shared_ptr删除器的使用:

void del(int *p) {
	cout << "del" << endl;
}

void func() {
	shared_ptr<int> p(new int(3), del);
	cout << p << endl;

	shared_ptr<int> p1(new int(4), [](int *p) { cout << p << endl; cout << "lambda" << endl; });
	cout << p1 << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高二的笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值