每日复习笔记5.5
C++复习笔记
c++ primer笔记
类(一)
类的定义与声明
类定义
- 类成员
每个类可以没有成员,也可以有多个成员,成员既可以是数据,也可以是函数或者类型别名。
一个类可以包括共有的(public)、私有的(private)和受保护(protected)成员。其中public部分定义的成员可以被该类型的所有代码访问;在private部分定义的成员可被其他类成员访问;在protected部分定义的成员可以被该类以及派生类的成员访问。
所有的成员必须在类的内部声明,但可以在类外定义。一旦类的定义完成,就没有任何方式可以添加成员。
- 构造函数
构造函数是一个特殊的、与类同名的成员函数,用于给每个数据成员设置适当的初始化。
- 成员函数
在类内部,声明成员函数是必需的,但成员函数的定义既可以在类内定义,也可以在类外定义。其中在类内定义的函数默认为inline(内联函数)。
数据抽象和封装
- 利用访问标号实现抽象和封装
访问标号是指public,protected,private三种。
a)程序的所有部分都可以访问带有public标号的成员。类型的数据抽象视图是由其public成员定义。
b)使用类的代码不可以访问带有private标号的成员。private封装了类型的实现细节。
- 数据抽象和封装
数据抽象和封装提供的两个重要优点:
·避免类内部出现无意的,可能破坏对象状态的用户级错误。
·随时间推移可以根据需求改变或缺陷报告来完善类实现,而无需改变用户级的代码。
类声明与类定义
在一个给定的源文件中,类声明可以多次,但是类定义只能出现一次。
可以声明一个类但是不定义它:
class Screen;
这个声明被称为前向声明。在声明之后,定义之前,类Screen是一个不完全类型。已知这是一个类型,但是不知道类型里包含哪些成员。
不完全类型不能定义该类型的对象。只能用于定义指向该类型的指针及引用,或者用于声明(而不是定义)使用该类型作为形参类型或返回类型的函数。
类对象
定义一个类时,相当于定义了一个类型。定义对象时,将为其分配存储空间,但定义类型时,不进行内存分配。
隐含的this指针
- 使用this指针的情况
有一种情况下必须这样做:当我们需要对一个对象作为整体引用而不是引用对象的一个成员。最常见的使用this的情况:该函数返回对调用该函数对象的引用。
- 从const成员函数返回*this
在普通的非const成员函数中,this类型是一个指向类类型的const指针(指针的值不可变,但是指向的值可变)。在const成员函数中,this类型是一个指向const类类型对象的const指针。既不能改变this所指向的对象,也不能改变this指向的地址。
类作用域
每个类都定义了自己的新作用域和唯一的类型。
构造函数
构造函数是特殊的成员函数,只要创建类类型的新对象,都要执行构造函数。
构造函数时不能声明为const的。
- 构造函数初始化式
和任何其他函数一样,构造函数具有名字、形参表和函数体。但是和其他函数不同的是,构造函数也可以包含一个构造函数初始化列表。
Sales_item::Sales_item(const string &book):
isbn(book), units_sold(0), revenue(0.0) {}
构造函数初始化列表以一个冒号开始,接着是一个以逗号分割的数据成员列表,每个数据成员后面跟一个放在圆括号中的初始化式。
如果这个类没有默认构造函数,在这个情况下,为了初始化数据成员,必须提供初始化式。
一般来说,成员被初始化的次序就是定义成员的次序。
- 构造函数也是可以使用默认实参对参数初始化
默认构造函数
- 合成的默认构造函数
一个类只要显式的定义了一个构造函数,编译器就不会再生成默认构造函数。
默认构造函数使用与变量初始化相同的规则来初始化成员。具有类类型的成员通过运行各自的默认构造函数来进行初始化。内置和复合类型成员,例如指针和数组,只对定义在全局作用域的对象才初始化。当对象定义在局部作用域中时,内置或复合类型成员不进行初始化。
如果类中包含内置或者复合类型的成员,则该类不应该依赖于合成的默认构造函数。应当定义自己的构造函数来初始化这些成员。
- 类通常需要定义一个默认构造函数
即使已经定义了其他的构造函数,提供一个默认构造函数总是没有错的。通常,在默认构造函数中给成员提供的初始化值应当指出该对象是“空对象”。
友元
友元机制允许一个类将对其非公有成员的访问权授予指定的函数或者类。友元的声明以关键字friend开始。他只能出现在类定义的内部。
class Screnn{
friend class Window_Mgr;
}
这里将Window_Mgr类声明为Screen类的一个友元类,Window_Mgr类的成员可以直接使用Screen类的私有成员。
也可以将其他类的成员函数设为友元。
这里需要理解,不只是类可以成为友元,类的成员函数也可以被设置为友元。而且还要注意的是,**一个类必须先定义过,才可以被声明为其他类的友元。
static类成员
static类成员的适用的场景:
在程序的任何一点需要统计已经创建的特定类类型对象的数量;或者全局对象可能只是指向类的错误处理历程的一个指针;再或者,它是指向类类型对象的内存自由存储区的一个指针。
全局对象会破坏类的封装性,所以想要完成上述工作的时候,类就可以定义static成员。static数据成员独立于类的任何一个对象,每个static数据成员都是与类本身关联的对象。
static成员函数可以直接访问所属类的static成员,但是不能直接使用非static成员。
- 使用static成员的优点
a)static成员的名字是在类的作用域中,因此可以避免与其它类的成员或全局对象的名字冲突。
b)可以实施封装。static成员可以是私有成员。但是全局对象不可以。
c)使程序更易读。因为static成员总是和特定的类关联,可以明确程序的意图。
- 定义static成员
例如
class Account{
public:
void applyint(){
amount += amount * interestRate;
}
static double rate(){
return interestRate;
}
static double rate(double);
private:
string owner;
double account;
static double interestRate;
static double initRate;
}
static成员函数
因为static成员是类的组成部分但不是任何对象的组成部分,所以static成员函数并没有this指针。