1.类和对象的概念
类:即class,代表着一类对象
对象:是类的实例,class里的每一个变量、每一个函数都是一个对象
class起到封装的作用,将不同的函数或变量封装在不同的类之下。
区别于结构体的封装
2.三种访问类型
内含三种访问类型,且格式为:
class 类名
{//大括号内的被成为 类体
public:
//公有的数据和函数
protected:
//保护的数据和函数
private:
//私有的数据和函数
};
例子有:
class Point{//例子:定义一个类用于一个点的使用
public://能用于外界使用的函数
void Point_set(int x, int y) {...}//函数体省略
void Point_move(int x, int y) {...}//函数体省略
void Point_origin();//这里只是声明一个函数
char Point_name[10];
private://表示相关属性,私有的
int x_0;
int y_0 = 10;//错误,不能在类中被显示的初始化
};
void Point::Point_origin() {
cout << x_0 << y_0;//使用外部接口可以在类外对类内公有成员函数进行操作
}
void main() {
Point P;
cin >> P.Point_name;
cout << P.x_0;//错误,外部函数对私有成员的访问都是非法的
//此外还可以调用其中函数,略
}
关键字private、public、protected称为访问权限修饰符或访问控制修饰符,用于限制类成员的控制访问范围,如果没有使用,默认为private,这些关键字的声明顺序和次数都是任意的。
类中的成员具有不同的访问权限修饰符。 从访问权限上来讲,类的成员又分为公有的
(public)私有的(private)和保护的(protected)3类:
- 公有成员定义了类的外部接口,只有公有成员才能被用户程序直接访问;
- 私有成*员定义了类的内部使用的数据和函数,私有成员只能被自己所属类的成员函数
及友元函数访问; - 保护成员访问权限介于公有成员和私有成员之间,它在类的继承和派生中使用。
除了静态数据成员(static)外,不能在类中被显示的初始化
3.内联函数
应对于宏函数,一种比较特殊的函数
内联函数有三种:
(1)直接在类内部定义。
(2)在类内部声明,加上inline关键字,在类外部定义。
(3)在类内部声明,在类外部定义,同时加上inline关键字。注意:此种情况下,内联函数的定义通常应该放在类定义的同一头文件中,而不是在源文件中。这是为了保证内联函数的定义在调用该函数的每个源文件中是可见的。
内联函数不是必须要inline,内联函数用于替代宏函数,仅适用于简单一点的函数,复杂函数会被编译器普通化
(普通函数的调用必须将程序执行的顺序转移到函数所在地址中,执行完函数后,再返回到之前的地址;而内联函数则不需要这些步骤,它直接展开了)
4.构造函数、析构函数、拷贝构造函数
4.1构造函数
是一个特殊的公共成员(public)函数,在创建类对象时会被自动调用,默认也是会存在的,即使没有编写。
-
函数名与类名相同,不允许有返回值
-
作用:初始化类里定义的变量(类里任何变量不允许有初始值)
-
可以带参数,可以重载
-
参数列表为空或所有参数都有默认值,被称为**默认构造函数 **
4.2析构函数
类中一个用于清理对象的特殊成员函数,与构造函数相对,释放资源(如动态分配内存之后),自动调用
- 函数名为类名前加一个取反符号"~",不允许有返回值
- 作用:释放资源之类的清理工作
- 不允许带参数,不能重载
4.3拷贝构造函数
一个特殊的构造函数,只有一个参数,且这个参数是对类对象的引用,即一般构造函数调用于参数是一般数据时,此构造函数调用于参数是类的对象,意为拷贝参数对象的值赋值给定义的新的对象,其他特性同构造函数
普通构造函数只在对象创建时被自动调用,而拷贝构造函数可以在下面3种情况下被自动调用。
-
用类的已知对象定义该类的一个正在被创建的对象。
-
对象作为函数的实参传递给函数形参。
-
对象作为函数返回值。
class Point{
public:
Point(int x,int y){//构造函数
x_0 = x;
y_0 = y;
}
/*
Point(int x = 1,int y = 1){//此参数为默认值,为默认构造函数
x_0 = x;
y_0 = y;
}
*/
~ Point(){//析构函数
}
Point(const Point &point){//拷贝构造函数,固定格式:const
}
...//其他省略
}
int main(){
Point *P = new Point(5,500);
return 0;
}
注意:
调用一个类,必然会先调用其构造函数,最后再调用析构函数,所以构造/析构函数里有输出,这时也会输出(不要忘了)
用堆运算符new给单个对象分配空间时,就是调用构造函数,如果是数组,就调用n遍;用delete删除时,就是调用析构函数。另外,使用了new/delete,构造/析构函数的调用顺序就可以人为改变,但对于一个对象还是先构造后析构。
5.this指针
this指针是用于保存当前对象地址而自动生成的隐含指针
- this指针只能在类的成员函数中使用,它指向该成员函数被调用的函数。this指针一般用于返回当前对象自身。
- 静态成员函数没有this指针。因为类只有一个静态成员函数实例,所以this指针没有什么用,且对其使用会有编译错误。
- 友元函数不属于类,所以友元函数没有this指针。
同其他指针一样的用法,运算符:“*”、"->",指向自身地址
class Point{
public:
void SetPoint(int x,int y){
this -> x_0 = x;
this -> y_0 = y;
}
void OutPoint(){
cout << "x=" << this->x_0 <<"y=" << this->y_0 << endl;
}
private:
int x_0;
int y_o;
...//其他省略
}
6.友元
介于类的封装性和隐藏性,只有类的成员函数才能访问类的私有成员,外部函数只能访问类的公有成员。为了一些特殊情况,引入友元来访问类的私有成员和保护成员。
友元可以是函数,即友元函数;也可以是类,即友元类
友元函数是外部的函数,只是为了访问私有成员而写到了类的里面。牺牲了类的封装性
格式为:friend <数据类型> <友元函数名>(形参)
例如:
class Point{
public:
friend void SetPoint(int x,int y){
this -> x_0 = x;
this -> y_0 = y;
}
friend void OutPoint(Point &p);//在内部声明一下即可
private:
int x_0;
int y_o;
...//其他省略
}
void OutPoint(Point &p){
cout << "x=" << p.x_0<< "y=" << p.y_0 << endl;
}//引用的时候必须要加上对象名
void main{
Point p1(10, 10);
OutPoint(p1);//代入参数
}
7.成员对象
一个类的成员是另外一个类的对象时,该对象就称为成员对象
成员函数在类中也需要被初始化,同样在构造函数中被初始化,为了明白到底在哪个构造函数中被初始化,因此对构造函数添加初始化列表,定义如下:
<类名> :: <类名> (<总参数表>): <成员对象名1>(<形参表1>), <成员对象名2>(<形参表2>), …
{…}
- 形参表对应总形参表的一部分
- 初始化成员对象时,也调用了那个类的成员,有输出即会输出之类的
- 成员对象的成员只能是公开函数或变量