《C++Primer》v5读书笔记
使用类定义自己的数据类型。通过定义新的类型来反映待解决问题的各种概念,可以使我们更容易编写、调试和修改程序。类的基本思想是数据抽象和封装。
数据抽象是一种依赖于接口和实现分离的编程技术。类的接口包括用户所能执行的操作;类的实现则包括类的数据成员、负责接口实现的函数以及定义类所需的各种私有函数。
封装实现了类的接口和实现的分类。封装后的类隐藏了它的实现细节,类的用户只能使用接口而无法访问实现部分。
抽象数据类型能帮助我们将对象的具体实现和对象所能执行的操作分离开来。
设计类的接口时,应该考虑如何实现用户的需求,考虑如何才能使得类易于使用;使用类的接口时,不应该顾及类的实现机理。
定义成员函数的方式与普通函数差不多。成员函数的声明必须在类的内部,它的定义则可在类的内部或外部。
定义在类内部的函数是隐式的inline函数。
1、引入this
成员函数通过一个名为this的额外的隐式参数来访问调用它的那个对象。当我们调用一个成员函数时,用请求该函数的对象地址初始化this。例如,如果调用
total.isbn()
则编译器负责把total的地址传递给isbn的隐式形参this。
this是一个常量指针,我们不允许改变this中保存的地址。
2、引入const成员函数
std::string isbn() const {return bookNo;}
const的作用是修改隐式this指针的类型。默认情况下,this的类型是指向类类型非常量版本的常量指针。因为在isbn函数体内不会改变this所指向的对象,把this设置为指向常量的指针有助于提高函数的灵活性。
像这样使用const的成员函数被称作常量成员函数。
常量对象,以及常量对象的引用或指针,都只能调用常量成员函数。
3、类作用域和成员函数
类本身就是一个作用域,类的成员函数的定义嵌套在类的作用域之内。
编译器分两步处理类:首先编译成员的声明,然后才轮到成员函数体。当我们在类的外部定义成员函数时,成员函数的定义必须与它的声明匹配。
一般来说,如果非成员函数时类接口的组成部分,则这些函数的声明应该与类在同一个头文件中。
4、构造函数
每个类都分别定义了它的对象被初始化的方式,类通过一个或几个特殊的成员函数来控制其对象的初始化过程,这些函数叫构造函数。
构造函数的任务是初始化类对象的数据成员,无论何时只要类的对象被创建,就会执行构造函数。
构造函数的名字和类名相同,和其他函数不一样的是,没有返回类型;
与其他函数类似,构造函数也有一个(可能为空的)参数列表和一个(可能为空的)函数体;
类可以包括多个构造函数,和其他重载函数差不多,不同的构造函数之间必须在参数数量或类型上有差别;
构造函数不能被声明为const的。当创建类的一个const对象时,直到构造函数完成初始化过程,对象才真正取得其“常量”特性。
默认构造函数
类通过一个特殊的构造函数来控制默认初始化过程,这个函数叫做默认构造函数。
默认构造函数无须任何实参。
只有当类没有生命任何构造函数时,编译器才会自动生成一个默认的构造函数。
如果类包含有内置类型或者复合类型的成员,则只有当这些成员全都被赋予了类内的初始值时,这个类才适合于使用合成的默认构造函数。
构造函数初始值列表
Sale_data(const std::string &s):bookNo(s){ }
Sale_data(const std::string &s, unsigned n,double p):
bookNo(s),units_sole(n),revenue(p*n) { }
构造函数的唯一目的是为数据成员赋值,一旦没有其他任务需要执行,函数体就为空。
在类的外部定义构造函数
Sale_data::Sale_data(std::istream &is){
return(is,*this) //read函数的作用是从is中读取一个交易信息
//然后存入this对象中
}
当在类的外部定义构造函数时,必须指明该构造函数时哪个类的成员。因为该成员的名字同类名相同,所以它是一个构造函数。
5、拷贝、赋值和构析
很多需要动态内存的类能使用vector或string对象管理必要的存储空间。使用vector或string的类能避免分配和释放内存带来的复杂性。
如果类包含vector或string成员,则其拷贝、赋值和销毁的合成版本能够正常工作。
在学习第十三章拷贝控制 关于如何自定义操作的知识之前,类中所有分配的资源都应该直接以类的数据成员的形式存储。
,只有被编译器需要的默认构造函数,编译器才会合成它。
原文:https://www.cnblogs.com/Summer-8918/p/10226386.html