语言设计就是库设计

前面一篇库设计就是语言设计 向我们展示了在设计类库的过程中,会遇到与设计语言相似的问题. 这一篇中我们将考虑相反的方向: c++中那些简化库设计的部分.
理解C++提供的各种支持库构造的功能,将帮助我们跟容易的理解和记住这些功能的用法.

§抽象数据类型

既然我们希望接口和实现完全分离,就会希望语言支持数据抽象.C++提供了很多关于数据抽象的概念.这样就可以不用再通过神奇的cookies和约定进行开发了.

构造函数和析构函数

C++提供的最基本的方式就是通过构造函数和析构函数实现接口和实现的分离.类似于RAII的方式.构造函数提供了生成给定类对象的方法,析构函数提供了释放给定类对象的方法.
我们可以通过修改构造函数和析构函数,修改类的实现方式,但是不会影响库使用者的代码.

成员函数和可见度控制

这个思想来源于OOP的封装思想.我们仅需要向用户暴露必要的信息,隐藏实现的信息.

§库和抽象数据类型

C++为库设计提供了比抽象数据类型更多的功能.以保证库设计者可以专注于类库的设计工作.

类型安全的链接

C++支持函数重载,C语言不支持重名函数.C++为了与C程序库兼容,采用了extern "C" {}的方式标注给编译器采用应该采用C函数的方式来处理其中的内容.并且C++所有的函数都是支持重载的,其中重点关注的应该是const的重载.

命名空间

C和C++都存在着一个很重要的问题,如何防止不同的库作者采用相同的名字.为了解决这个问题,C++引入了命名空间这个概念.用户可以通过指明命名空间的方式和采用using namespace xxxxxx命名空间中的所有名字引入.

§内存分配

C++可以使用new操作符创建并初始化一个对象.可以通过delete操作符销毁一个创建在动态内存上的对象.
如果我们需要进行与默认方式不同的方法创建一个类的对象呢?
C++提供了void* operator new(size_t)void operator delete(void*)连个操作符重载的功能.只要我们完成了重载,那么只要在动态内存空间创建和销毁这个类的对象都会使用我们定制化的操作.
其中我们还可以指定一块空间的地址,将类对象直接在这块空间中创建出来.这个使用了placement new的语义. 使用方式如下:

void *p = /*一块空间*/
T* tp = new(p) T;

C++同样针对这个操作提供了operator new的另外一个重载版本:void* operator new(size_t, void* p);我们可以通过重载这个操作符实现自己的placement new的语义.

§按成员赋值和初始化

根据C语言的结构体的语义:

struct Point {
    int x, y;
};

Point p1;
p1.x = 0;
p1.y = -1;
Point p2 = p1;

最后一条语句的含义是:将p1的内容复制一份给p2.这里的复制是将Point类型底层的接口按位复制的.C++中我们可以通过拷贝构造函数和operator=精准的控制应该怎样进行复制.但是针对一些包含复杂成员的简单类还要定义专属的拷贝构造函数和赋值操作符是很麻烦的事情.

class Person {
    String name, address, telno;
    Person();
    Person(const Person& p): name(p.name), address(p.address),telno(p.telno) {}
    Person& operator=(const Person& p) {
        name = p.name;
        address = p.address;
        telno = p.telno;
        retrun *this;
    }
};

我们不需要提供析构函数,因为编译器提供的析构函数在析构成员变量的时候会执行String的析构函数.所以C++完善了这个措施,既然析构函数可以使用成员变量的析构函数析构,那为什么不能使用成员变量的拷贝构造函数和赋值操作符来进行拷贝和赋值呢? 所以现在C++的拷贝和赋值操作符的默认实现已经不是按位复制了,而是会使用成员变量类型提供的拷贝和赋值操作符.

§异常处理

C++提供的异常处理机制简化了用户每次都需要检查是否合法的负担,同时也简化了类设计者实现的负担.

你可能感兴趣的:(语言设计就是库设计)