第十二章、类(注意的地方)
一、定义和声明:
1、 类就是定义了一个新的类型和新的作用域
2、 一个类可以包含若干个公有的,私有的和受保护的部分。在public部分定义的成员可以被使用该类型的所有代码访问;在private部分定义的成员可被其他类成员访问。
3、 构造函数:是一个特殊的、与类同名的成员函数,用于给每个数据成员设置适当的初始化。如:Sales_item(允许有参数):units_sold(0),revenue(0.0){ }
构造函数初始化列表由成员名和带括号的初始化值组成,跟在构造函数的形参表后面,并以冒号开头。
4、 成员函数:在类内部,声明成员函数是必须的。而定义成员函数是可选的。
5、 数据抽象和封装:类背后蕴含的基本思想是数据抽象和封装。
数据抽象是一种依赖于接口和师兄分离的变成技术;
封装是一项将低层次的元素组合起来形成新的、高层次实体的技术。类也是一个封装的实体:它代表若干成员的聚集,大多数良好设计的类类型隐藏了实现该类型的成员。
数据抽象和封装有两个优点:
(1) 避免类内部出现无意的、可能破坏队形状态的用户级错误。
(2) 随时间退役可以根据需求改变或缺陷报告来完善类实现,而无需改变用户级代码
6、 将类定义放在头文件中,可以保证在每个使用类的文件中以同样的方式定义类。
7、 定义对象时,将为其分配存储空间,但是一般在定义类型时不进行分配存储空间。
定义了一个类类型后,可以按以下两种方式使用:
(1) 将类的名字直接用作类型名。
(2) 指定关键字class或struct,后面跟着类的名字。
二、隐含的this指针
1、 this是一个指向非常量Screen的指针,可以通过对this指针解引用来访问this指向的对象。
2、 在普通的非const成员函数中,this的类型时一个指向类类型的const指针。可以改变this所指向对象的值,但不能改变this所保存的地址。在const成员函数中,this的类型时一个指向const类类型对象的const指针。既不能改变this所指向的对象的值,也不能改变this所保存的地址。
3、 可变数据成员:永远都不能为const,甚至当他是const对象的成员也如此。需要将关键字mutable放在成员声明之前: mutable size_t access_ctr;
三、类作用域:两个不同的类具有两个不同的类作用域。
1、 即使两个类具有完全相同的成员列表,他们也是不同的类型。每个类的成员不同于任何其他类的成员。
2、 使用类的成员:在类作用域之外,成员只能通过对象或者制作分别使用成员访问操作符.或者->来访问。
3、 作用域与成员定义:一旦看到成员的完全限定名,就知道该定义是在类作用域中。因为该定义是在类作用域中,所以我们可以直接引用成员revenue,而不用this->revenue;
四、构造函数:是特殊的成员函数,只要创建类类型的新对象,都要执行构造函数。构造函数的作用就是保证每个对象的数据成员具有合适的初始值。
1、 构造函数的名字与类的名字相同,并且不能指定返回类型。它们可以没有形参,也可以定义多个形参。
2、 构造函数不能声明为const。
3、 构造函数初始化式: Sales_item::sales_item(const string &book):isbn(book),
units_sold(0),revenue(0.0) { }
构造函数初始化列表以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个数据成员后面跟一个放在圆括号中的初始化式。
4、 可以初始化const对象或引用类型的对象,但不能对它们赋值。初始化const或引用类型数据成员的唯一机会是在构造函数初始化列表中。
下面的构造函数是错的:
Class constRef
{
Public:
constRef(int ii);
private:
int i;
const int ci ;
int &ri;
} ;
constRef::constRef(int ii)
{
I = ii ;
Ci = ii ; ci为const类型!
Ri = ii ;
}
构造函数改为:constRef::constRef(int ii): i(ii) , ci(ii), ri (ii) { }
5、 只有当一个类没有定义构造函数时,编译器才会自动生成一个默认构造函数,当有一个构造函数时,编译器都不会提供默认构造函数。
五、友元:机制允许一个类将对其非公有成的访问权授予指定的函数或类。友元的声明以关键字friend开始。将友元声明成组的放在类定义的开始或结尾时好主意!
1、 友元函数可以再类的内部定义,该函数的作用域扩展到包围该类定义的作用域。
2、 友元引入的类名和函数(声明和定义),可以像预先声明的一样使用:
Class X
{
Friend class Y;
Friend void F();
} ;
Class Z
{
Y*ymen;
Void g() {return ::F() ; }
} ;
六、static类成员:类可以定义类静态成员。Static数据成员独立于该类的任意对象而存在;每个static数据成员是与类关联的对象,并不与该类的对象关联。
1、 static成员函数没有this形参,它可以直接访问所属类的static成员,但不能直接使用费static成员。
2、 使用类的static成员的优点:
(1) static成员的名字是在类的作用域中,因此可以避免与其他类的成员或全局对象名冲突。
(2) 可以实施封装,全局对象不可以。
(3) 容易看出static成员是与特定类关联的,清晰显示程序员的意图。
3、 成员声明前加上关键字static将成员设为static。Static成员遵循正常的公有、私有访问规则。
4、 像是要其他成员一样,类成员函数可以不用作用操作符来引用类的static成员。
5、 Static数据成员必须在类定义体的外部定义(正好一次)。不想普通数据成员,static成员不是通过类构造函数进行初始化,而是应该在定义时初始化。
Double Acconut::interestRate = initRate();语句定义名为interestRate的static对象,他是类Account的成员,为double型。
6、 static关键字只能用于类定义体内部的声明中,定义不能标为static。
7、 static成员独立于任何对象而存在,不是类类型对象的组成部分。因为static数据成员不是任何对象的组成部分,所以他们的使用方式对于非static书丞而言是不合法的。例如:static数据成员的类型可以是该成员所属的类类型,非static成员被限定声明其自身类对象的指针或引用。
Class Bar
{
Public:
//
Private:
Static Bar mem1;正确
Bar *mem2 ;正确
Bar mem3;错误!
} ;