(一)类的定义
类是用户自定义数据类型。如果程序中要使用类类型,必须根据实际需要定义,或者使用已设计好的类。
C++定义一个类,其方法与定义一个结构体类型是相似的,一般形式为:
class 类名{//类体
成员列表
};
其中成员列表是类成员的集合,数目可以任意多,由具体应用确定。一对大括号{}是成员列表边界符,与成员列表一起称为类体。类体后面必须用分号结束。
每个类可以没有成员,也可以有多个成员。
类成员可以是数据或函数。
所有成员必须在类的内部声明,一旦类定义完成后,就没有任何其他方式可以再增加成员了。
类定义时必须给出各个数据成员的数据类型声明,其一般形式为:
class 类名{//类体
…
数据成员类型 数据成员名列表;//数据成员声明
…
};
声明时成员名列表允许为多个,用逗号作为间隔,最后必须用分号结束。
每个类还可以包含成员函数,能够访问类自身的所有成员。
面向对象程序设计一般将数据隐蔽起来,外部不能直接访问,而把成员函数作为对外界的接口,通过成员函数访问数据。即数据成员是属性,成员函数是方法,通过方法存取属性。
如果类中有成员函数,则声明成员函数是必需的,而定义成员函数则是可选的,因此类的成员函数有两种形式。
1.在类中定义成员函数,形式如下
class 类名{//类体
…
返回类型 函数名(形式参数列表)//成员函数定义
{
函数体
}
…
};
2.成员函数的声明在类中,定义在类外部,
class 类名{//类体
…
返回类型 函数名(类型1 参数名1,类型二 参数名二,…);
//成员函数声明
返回类型 函数名(类型1,类型二,…);
…
};
返回类型 类名::函数名(形式参数列表)
{
//成员函数定义在类外部实现
函数体
}
例题:
class Date{//Date类定义
void set(int d);
//成员函数原型声明,与void set(int);等价
int get(){//成员函数类内部定义
return data;
}//get函数定义结束
int data;//数据成员
};//Data类定义结束
void Data::set(int d)//成员函数类外部定义
{
data=d;//访问类的数据成员
}
类定义一般放在程序文件开头,或者放到头文件中被程序文件包含,此时这个定义是全局的。在全局作用域内,该定义处处可见,因此同作用域内的所有函数都可以使用它。
类定义也可以放到函数内部或局部作用域中,此时这个定义是局部的。若在函数内部有同名的类定义,则全局声明在该函数内部是无效的,有效的是局部定义的。
class Data{//全局的Data类定义
void show();//成员函数原型声明
int data;//数据成员
};//Data类定义结束
void fun()
{
//全局Data在fun函数中无效,有效的是局部定义的Data
class Data{//局部的Data类定义
void show(){cout<<data;}//set函数定义
int data;//数据成员
};//Data类定义结束
}
C++规定,在局部作用域中声明的类,成员函数必须是函数定义的形式,不能是原型声明。一般地,由于类是为整个程序服务的,因此很少有将类放到局部作用域中去定义。
类定义向编译器声明了一种新的数据类型,该数据类型有不同类型的数据成员和成员函数。因此尽管数据成员类似变量的定义,但类型声明时并不会产生该成员的实体,即为它分配存储空间。
对类的成员进行访问,来自两个访问源:类成员和类用户。
类成员指类本身的成员函数,类用户指类外部的使用者,包括全局函数、另一个类的成员函数等。
无论数据成员还是函数成员,类的每个成员都有访问控制属性,由以下三种访问标号说明:public(公有的)、private(私有的)和protected(保护的)。
公有成员用public标号声明,类成员和类用户都可以访问公有成员,任何一个来自类外部的类用户都必须通过公有成员来访问。显然,public实现了类的外部接口。
私有成员用private标号声明,只有类成员可以访问私有成员,类用户的访问是不允许的。显然,private实现了私有成员的隐蔽。
保护成员用protected标号声明,在不考虑继承的情况下,protectde的性质和private的性质一样,但保护成员可以被派生类的类成员访问。
类定义更一般的形式为:
class 类名{//类体
public://公有访问权限
公有的数据成员和成员函数
protected://保护访问权限
保护的数据成员和成员函数
private://私有访问权限
私有的数据成员和成员函数
};
如果没有声明访问控制属性,类所有的成员默认为private,即私有的。
说明:
1.在定义类时,声明为public、private或protected的成员次序任意。
2.在一个类体中不一定都包含public、private或protected部分,可以只有public、private或protected部分或任意组合。
3.关键字p可以访问ublic、private、protected可以分别出现多次,即一个类体可以包含多个public、private、或protected部分。但更通用的做法是将相同访问控制属性的成员集中在一起来写。
在成员函数中可以访问这个类的任何成员,无论它是公有的或是私有的,是类内部声明的还是外部定义的。
类的函数原型声明必须出现在成员函数定义之前。
(二)对象的定义
对象指类的实体。
1.先定义类类型再定义对象
例如:Point a,b;
2.定义类类型的同时定义对象
3.直接定义对象
一般而言,定义类型时不进行存储空间的分配。
当定义一个对象时,会为其分配存储空间。
利用new运算符可以动态地分配对象空间,delete运算符释放对象空间。
访问对象中的成员可以有三种方法:
1.通过对象名和对象成员引用运算符(.)访问对象中的成员;
2.通过指向对象的指针和指针成员引用运算符(->)访问对象中的成员;
3.通过对象的引用变量和对象成员引用运算符(.)访问对象中的成员;
1.通过对象名访问对象中的成员
访问对象中数据成员的一般形式为:
对象名.成员名
调用对象中成员函数的一般形式为:
对象名.成员函数(实参列表)
从类外部只能访问类公有的成员。
2.通过对象指针访问对象中的成员
访问对象中数据成员的一般形式为:
对象指针->成员名
调用对象中成员函数的一般形式为:
对象指针->成员函数(实参列表)
3.通过引用变量访问对象中的成员
访问对象中数据成员的一般形式为:
对象引用变量名.成员名
调用对象中成员函数的一般形式为:
对象引用变量名.成员函数(实参列表)
(三)构造函数
构造函数就是用来在创建对象时初始化对象,为对象数据成员赋初始值。
类的数据成员是不能在类定义时初始化的,因为类定义并没有产生一个实体,而是给出了一个数据类型,不占用存储空间,因而也无处容纳数据。
如果一个类中所有的数据成员是公有的,则可以在定义对象时对数据成员进行初始化,例如:
class Point{//Point类定义
public:
int x,y;//数据成员声明
…//其他成员
};
Point one={10,10};//对象初始化
Point A[3]={{10,10},{20,20},{30,30}};//对象数组初始化
如果类中的数据成员是私有的,就不能用这种方法初始化,因为外部不能直接访问私有的数据成员。
构造函数是类的一种特殊成员函数,不需要人为调用,而是在建立对象时自动被执行。
1.定义构造函数
C++规定构造函数的名字与类的名字相同,并且不能制定返回类型。
定义形式为:
类名(形式参数列表)
{
函数体
}
构造函数可以没有形参,有如下两种形式:
类名()
{
函数体
}
类名(void)
{
函数体
}
构造函数的重载
在一个类中可以定义多个构造函数版本,即构造函数允许被重载,只要每个构造函数的形参列表是唯一的。一个类的构造函数数量是没有限制的。一般地,不同的构造函数允许建立对象时用不同的方式来初始化数据成员。
尽管在一个类中可以包含多个构造函数,但是对每一个对象来说,建立对象时只执行其中一个,并非每个构造函数都执行。
定义默认构造函数
默认构造函数就是在没有显式提供初始化式时调用的构造函数,它是一个不带参数的构造函数。如果定义某个类的对象时没有提供初始化式就会使用默认构造函数。
如果为类定义了一个带参数的构造函数,还想要无参数的构造函数,就必须自己定义它。
复制构造函数
复制构造函数是一种特殊的构造函数。它的作用就是用一个已经生成的对象来初始化另一个同类的对象。
若复制对象但未复制资源内容称为浅复制。
如果一个拥有资源的类对象发生复制的时候,若对象数据与资源内容一起复制,称为深复制。
析构函数
当对象脱离其作用域时,系统会自动执行析构函数。
C++规定析构函数的名字是类名的前面加一个~。其定义形式为:
~类名()
{
函数体
}
析构函数不返回任何值,没有返回类型,也没有函数参数。由于没有函数参数,因此它不能被重载。换言之,一个类可以有多个构造函数,但是只能有一个析构函数。
何时调用析构函数:
(1)对象在程序运行超出其作用域时自动撤销,撤销时自动调用该对象的析构函数。如函数中的非静态局部对象。
(2)如果用new运算动态地建立了一个对象,那么用delete运算释放该对象时,调用该对象的析构函数.
类的成员函数如何区分不同的实例对象的数据成员呢?
C++为此专门设立了一个名为this的指针,用来指向不同的对象。
一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果。
对于知识点部分整理的不够精细.