类和对象
前言
总所周知,C语言是面向过程的编程,而C++则是面向对象的编程,面向过程是指按照事物逻辑顺序进行发展;面向对象则是将具有相同属性的对象抽象出来形成类,对象与对象之间进行交互,使得彼此之间状态发生改变,面向对象的语言有以下四种特点:抽象、封装、继承、多态;
了解面向对象的编程首先需要了解类以及类里面的一些定义;
一、类的定义
C++中用关键字class来定义一个类,基本形式如下所示:
class 类名
{
public:
//公有的数据成员和成员函数
protected:
//保护数据成员和成员函数
private:
//私有数据成员和成员函数,其中私有数据成员可以不能通过类进行显示调用,
//但是可以通过成员函数进行调用
};
class类中所有的东西默认都是私有的,成员函数可以在类中申明,在类外进行定义,在类外定义时,需要通过作用于限定符来标识所属的类;代码如下:
class Point
{
public:
void print();
private:
int _ix;
int _iy;
}
void Point::print()
{
cout<<"("<<_ix<<","<<_iy<<")"<<endl;
}
二、对象的创建与销毁
2.1、对象的创建
有了类之后,我们便需要考虑通过类来创建对象,其实C++创建对象是很简单的,代码如下所示:
Point pt;
这样便算是创建了一个Point的对象,但在这背后发生的过程也是我们需要关注的,当创建一个对象时,其实是调用了Point类的构造函数,但在上面的Point类中我们似乎并没有看到所谓的构造函数,这又是为什么呢?
因为当我们未自定义构造函数时会在编译器编译时自动生成构造函数,那么构造到底是什么样的呢?构造函数具有以下三个特点:
- 函数名和类名相同
- 没有返回值
- 没有返回类型,void也没有
接下来,我们可以自己写一个构造函数供类在创建对象时使用,代码如下:
class Point
{
public:
Point(int ix = 0,int iy = 0)
:_ix(ix)
,_iy(iy)
{
cout<<"调用构造函数"<<endl;
}
void print();
private:
int _ix;
int _iy;
}
void Point::print()
{
cout<<"("<<_ix<<","<<_iy<<")"<<endl;
}
这样我们便生成了一个构造函数,在Point(int ix = 0,int iy = 0)和函数体之间我们插入了初始化表达式,关于初始化表达式,我们需要注意的是:数据成员在进行初始化时,数据成员的初始化顺序只与数据成员被申明的顺序有关,即在Point类中,我们在;private中申明的_ix和_iy的顺序为先_ix再_iy,那么在构造函数初始化成员函数时便会按照先初始化_ix再初始化_iy的顺序,与初始化表达式中数据成员的顺序无关;
关于构造函数,我们还需要知道构造函数是可以进行重载的,但是构造函数是不能进行显示调用的;
2.2、对象的销毁
在了解到对象的创建后,对象销毁的问题随之而来,其实与构造函数一样,关于对象销毁是有编译自动生成的默认析构函数的,析构函数具有以下的特点:
- 与类同名,之前会加上波浪号
- 没有返回类型,没有参数,不能被重载
- 对象超出其作用域,析构函数会被自动调用
自己写一个析构函数的代码如下:
class Point
{
public:
Point(int ix = 0,int iy = 0)
:_ix(ix)
,_iy(iy)
{
cout<<"调用构造函数"<<endl;
}
~Point()
{
cout<<"调用析构函数"<<endl;
}
void print();
private:
int _ix;
int _iy;
}
void Point::print()
{
cout<<"("<<_ix<<","<<_iy<<")"<<endl;
}
析构函数不同于构造函数除了析构函数不能重载外,析构函数本身是可以由对象显示调用,但是往往是不建议显示调用析构函数;此外还需要注意析构函数在对象不同但作用域相同情况下的调用顺序:析构函数调用顺序是和构造函数相反的;
总结
已经实现了对象的创建以及销毁,那么剩下便可以开始面向类和对象的编程之旅了