类的定义:
⑴类是对具有相同属性和行为的一组对象的抽象与统一描述。是用户自定义的数据类型。
⑵类的定义包括行为和属性两个部分。
⑶属性以数据表示,行为通过函数实现。
类与对象的关系:
(1)对象是类的实例
(2)类是一组对象的抽象化模型
类是抽象的(类的成员是抽象的),对象是具体的(对象的成员是具体的)
基本定义格式:
class 类名
{
public:
公有成员
protect:
保护型成员
private:
私有成员
};
数据成员:属性
函数成员(成员函数):操作
内联成员函数
在类声明内(大括号之内)定义内联函数是可能的。如果一个函数是在类声明内定义的,它将自动的转换成内联函数(如果可能的话)。没有必要(但不是错误)在函数声明的前面再加上关键字inline。
此种情况
不加inline为隐式声明
添加inline为显示声明
成员函数不一定是内联函数:在类体内定义的成员函数都是内联函数,不在类体内定义的就不是内联函数
例:
class Student
{
public:
int a;
int b;
void get(); //仅进行成员函数声明,未定义(不为内联函数)
}
void student::get()
{
cout<<a<<" "<<b<<endl;
}
class Student
{
public:
int a;
int b;
void get(); //成员函数声明加定义(为内联函数)
{
cout<<a<<" "<<b<<endl;
}
}
成员函数的重载
对象的定义与使用
定义:
类名称 对象名;
使用:
对象名.成员名
注:
类的外部只能通过对象访问公有成员(public部分)
类的成员函数内部可以直接访问所有成员(public,protected,private)
类的作用域与可见性
类作用域(类的内部):类定义和相应的成员函数定义的内部(区别于类体内部 )
类作用域内,任意一个成员函数可以访问其他所有成员
类的可见性:
1.类的内部,与类或类的成员同名的全局变量或函数名不可见。(即不可使用)
也可以使用全局作用符
#include <stdio.h>
int count = 0; //全局变量 0
void main()
{
int count = 10; //局部变量10
printf("count =%d\n",count);//局部变量屏蔽了全局变量 所以输出结果是10
{
int count = 20;
printf("count =%d\n",::count); //作用域符号指出引用全局变量0
}
}
2.一个函数内部,同名的类和对象可以同时使用,都是可见的。
构造函数
根据参数可分为:缺省构造函数(默认构造函数(无参或参数均有缺省值))和用户自定义构造函数
完成对象的初始化,给对象的数据成员赋初值
特点:名称与类名相同,没有返回值,一定为公有函数
拷贝构造函数(复制构造函数):以对象(对象的引用)作为参数传给构造函数进行构造
例:
class student
{
public:
student(student &a);
}
由例子中可以看出传递的必须是对象的引用
拷贝构造函数分为深拷贝和浅拷贝
说明:类的数据成员包括指针变量(即占用堆空间),利用new给指针变量动态申请空间,即指向另一个内存,防止出现两个指针对象指向同一个堆地址,当其中一个被delete后,另一个会变成野指针,其中一个数值修改,另一个也会受到影响。
假定将A对象拷贝(赋值)给B对象
1.深拷贝
修改B对象的属性和方法不会影响到A对象的属性和方法(无指针变量的拷贝是深拷贝)
2.浅拷贝
修改B对象的属性和方法会影响到A对象的属性和方法(有指针变量,且拷贝过程中没有给予新空间,导致指针同一地址,改变改变其中一个对象的指针成员,另一个对象的指针成员也会跟着改变)
构造函数可以重载
析构函数
对象占用的空间需要通过析构函数来释放
不定义析构函数,系统会提供默认构造函数(无法释放堆内存)
即一般来说,指针作为数据成员时才需要定义析构函数
析构函数无法重载
类的封装性
封装性:数据 与操作数据的行为进行有机结合
对象数组
缺省构造函数:可直接定义 例如 Student a[5];
有参构造函数:因为有参数,必须逐个赋初值,方法多种
例如:
Student *a[2]={new Student(0),new Student(0)}
大多数情况对于有参构造函数过于鸡肋
对象作为函数形参
直接传递对象时类的数据成员需要一一复制,效率不高,可以使用对象指针或者对象引用
例 void get(Box *a); 或者 void get(Box &a);
对象指针
假设定义了Box类,有public成员int i,void get();
Box a; //栈中分配内存
Box *b=new Box; //堆中分配内存
Box *c=&a; //堆中分配内存,此种方式导致地址相同
对象指针访问成员时采用——对象名->成员
例:
Box *b=new Box; //堆中分配内存
b->get();
b->i=1;
this指针
上面提到,类的内部任意一个成员函数可以访问所有的成员,访问方式就是采用this指针
class student
{
public:
void get();
private:
int x;
}
void student::get()
{
cout<<this->x; //或者写为cout<<x;
}
由例子可以看出this指针可以省略
即:this->成员 <=> 成员;