您当前的位置: 首页 >  c++

我什么都布吉岛

暂无认证

  • 2浏览

    0关注

    292博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Effective C++ (四)设计与声明

我什么都布吉岛 发布时间:2021-07-30 10:04:00 ,浏览量:2

什么是软件设计?作者认为“令软件做出你希望它做的事情”的步骤和方法。

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

一个接口不能假设使用者都为“讲道理的人”,开发一个容易被使用,不容易被误用的程序可以做哪些工作呢?

  • 函数代替对象 以一个日期类的构造函数为例,说明接口的重要性
class Date
{
public:
	Date(int month,int day,int year);
}

用户实际使用的时候可能会顺序调换,无效参数(21月)。可以使用一个外覆类型(wrapper types)来区分过滤掉用户可能不正确输入。本例而言的具体做法是:

struct Day
{
	explicit Day(int d):val(d){}
	int val;
}
struct Month
{
	explicit Month(int m):val(m){}
	int val;
}
struct Year
{
	explicit Year(int y):val(y){}
	int val;
}
class Date
{
public:
	Date(const Year& y, const Month& m, const Day& d){...}
}

将接口改成上面这样,用户按照你的设想输入参数:

Date d(30,3,1995);						//error,类型不匹配
Date d(Day(30),Month(3),Year(1995));	//error,类型不匹配,顺序
Date d(Year(1995),Month(3),Day(15));		//ok,类型顺序都匹配

当时仍然无法阻止用户输入Month(15)这种操作,因为日期的取值是固定的,其实现阶段最佳的实现方式是enum class,在作者写这本书时尚未支持。

  • const修饰operator* 等操作符

  • 尽可以能和内置类型保持一致

  • 令factory模式返回指定类型

回忆之前的例子,为了保证调用者使用智能指针管理内存,将createInvestment的返回值修改为std::shared_ptr

Investment * createInvestment();      //构造接口
void getRidOfInvestment(Investment*); //析构函数

std::shared_ptr createInvestment();

默认情况std::shared_ptr是用delete回收资源的,但是这个例子却使用了一个自定义函数getRidOfInvestment,std::shared_ptr的第二个参数是一个删除器deleter,传递之:

std::shared_ptr createInvestment()
{
	std::shared_ptr retVal(nullptr,getRidOfInvestment);//不太清楚书中为什么坚持要用static_cast,nullptr不是可以隐式转换成任何类型吗?
	//可能做一些Investment的一些特化操作
	//如果能够在std::shared_ptr之前确定,那更倾向于和构造一起
	//而不是指向空在指向对象,效率上可能慢一点
	//retVal指向真正的对象,retVal.reset(...)
	return retVal;
}

最后作者总结了一下使用智能指针的

优点:

  • cross-DLL智能指针总能正确调用资源析构
  • 智能指针可以消除潜在的内存泄漏

和缺点:

  • 大小可能是原始指针(raw pointer)的两倍
  • 需要辅助内存
  • 速度稍微慢一些
条款19 设计class犹如设计type

设计class其实就是设计一个新类型,设计目标是和标准体验一致。设计之前应该考虑:

  • 新的type应该如何被创建和销毁
  • 对象初始化和赋值有什么差别
  • 对象拷贝时行为
  • 成员变量合法性是否在构造、赋值和setXXX的函数进行了检查、异常处理
  • 新类型的继承图系(inheritance graph)
  • 需要什么类型转换?显式还是隐式?见条款15
  • 什么样的操作和函数对于对象是合理的
  • 编译器默默构造的函数行为是否符合预期?条款6
  • type的访问控制如何?
  • 什么是新type的为声明接口
  • 若为一系列的类应该考虑template
  • 你真的需要定义一个新type吗?

暂时不能有更深入的理解,毕竟设计好的class是一个非常系统的工程。等以后再继续看吧,留个坑

条款20 宁以pass-by-reference-to-const代替pass-by-value

为什么要这么做?

  1. 拷贝构造是需要成本的
  2. 继承关系中派生类失去特性

假设我们定义了一个类A:

class A
{
public:
	A() { std::cout             
关注
打赏
1658157489
查看更多评论
0.0397s