c++面向对象编程

来源:互联网 发布:linux count 命令 编辑:程序博客网 时间:2024/05/29 23:47
最近在学习c++,这篇博客权当学习笔记吧。先上一段代码吧:

#include <iostream>using namespace std; class Clock{     //定义时钟类public:void setTime(int newH = 0,int newM=0;int newS = 0);void showTime();private:int hour,minute,second;};//定义函数setTimevoid Clock::setTime(int newH = 0,int newM=0;int newS = 0){hour = newH;minute = newM;second = newS;}//定义函数showTime()inline void Clock::showTime(){cout<<hour<<":"<<minute<<":"<<second<<endl;}int main(){Clock myClock;    //创建一个对象(实例化一个类)cout<<"First time set and output:"<<endl;myClock.setTime();myClock.showTime();cout<<"Second time set and output:"<<endl;myClock.setTime();myClock.showTime();return 0;}

0x1面向对象or面向过程

看了代码我们先来讨论一下什么是面向对象的编程,什么又是面向过程?

学过c语言的人都知道,c就是一门面向过程的语言,面向过程的主要特点就是我们写代码时注重的是某件事正在发生,而面向对象的话则是关心围绕着某一事物都发生了什么,重点在事物

0x2类的定义与创建对象

上面的代码定义了一个时钟类,并在主函数中实例化了该类,对该对象进行了各种操作。下面我们就围绕着这一串代码进行探讨有关c++的面向对象编程。

从上面的代码我们可以看到,定义一个类要用到关键词class,格式为 :

class 类名{

这里就是类的一些函数与属性;

};(这里有分号)

定义了类过后要想使用该类就需要先实例化该类,也就是用该类创建一个对象(当然创建对象时在主函数当中进行的),相应的语法为:

类名 对象名;(具体应用请参考上述代码)

大家是不是想到了c语言中的结构体?还记得结构体是怎么用的吗?不就是和这里的类有异曲同工之处吗!但是大家也注意到类中有函数的存在,这是结构体中没有的,类中的结构体我更喜欢叫他们为方法,意思是做一件事的需要进行的处理,而类中的变量叫做属性。

当然我们也可以把类理解为我们自己定义的一种数据类型(虽然它本质不是这样的),而创建一个类的对象就可以类比为我们创建一个变量。

0x3访问控制

除了函数与属性外,大家看到上面的类中有public,private,protected等关键字,这些就涉及到类的一个特点了,这种特点叫做访问控制,而这些关键词就是明确他们冒号后的函数或者属性能够被那些东西访问。

private:只能由1.该类中的函数、2.其友元函数访问。
不能被任何其他访问,该类的对象也不能访问。

protected:可以被1.该类中的函数、2.子类的函数、以及3.其友元函数访问。
但不能被该类的对象访问。

public:可以被1.该类中的函数、2.子类的函数、3.其友元函数访问,也可以由4.该类的对象访问。(有关子类,友元函数的概念将在后续进行介绍)

0x4成员函数

下面再仔细说一下类中的函数吧,类的成员函数分为一般函数、构造函数、析构函数。一般函数就不说了,构造函数(他的名字与类的名字一样,这是规定)是在类创建对象时自动调用的,而且它是最先被调用的,他的作用一般是初始化对象,为对象的属性赋初值等等。而析构函数和构造函数恰恰相反(他的名字则是在类的名字前面加一个~符号),他是在程序运行结束时自动被调用的,它用来做一些收尾工作,例如释放对象占据的存储空间啊等等,如果你想要在程序结束时做一些事情,也可以写在析构函数里。当然既然是自动调用这两个函数,那么这两个函数也就是默认的函数啦,即使我们不亲自去编写它们,它们也是存在的,只是没有显示出来而已,默认的构造与析构函数都是空的,但是这并不代表它们就没有用,这一点大家以后就会有体会了。对了构造函数还有一个比较特殊的类别那就是复制构造函数,复制构造函数顾名思义就是用来复制用的,它是用来复制对象的(毕竟有时候我们会用到拷贝对象这一功能),这个函数也是默认的,默认就是一个拷贝功能,但是同样的,我们还是可以自己对该函数进行编写,来实现自己想要的功能,如果只是简单的实现复制对象功能的话,复制构造函数不需要写出来,因为它是默认的功能。

对了,复制构造函数必须是引用调用

为方便大家理解,下面贴上几段代码分别说明构造函数与析构函数以及复制构造函数怎么定义与使用:

class Clock{public:Clock((int newH,int newM,int newS));       //构造函数的声明void setTime(int newH,int newM,int newS);void showTime();private:int hour,minute,second;};//构造函数的定义Clock::Clock((int newH,int newM,int newS)){hour = newH;minute = newM;second = newS;}int main(){Clock c(0,0,0);    //声明一个对象,并赋初值,这一步会自动调用构造函数c.showTime();     //屏幕输出初始时间c.setTime(1,1,1);    //重新设置时间return 0;}
析构函数,此处我没有自己定义析构函数,只是显式地将他写了出来,帮助大家理解:


class Clock{public:Clock();void setTime(int newH,int newM,int newS);void showTime();~Clock();         //析构函数private:int hour,minute,second;}


复制构造函数:

class Point{public:Point(int xx = 0,int yy = 0){x = xx;y = yy;}Point(Point &p);  //声明复制构造函数int getX(){return x;}int getY(){return y;}private:int x,y;};//复制构造函数的定义Point::Point(Point &p){x = p.x;               y = p.y;cout<<"calling the copy construct!"<<endl;}//直接将元对象的两个属性复制给新的对象



0x5复制构造函数

值得注意的是,在有几个情况下会调用复制构造函数,可能这些场景你都不会想到:

1.当用类的一个对象去初始化该类的另一个对象时。

2.如果函数的形参是类的对象,调用该函数时,进行形参和实参的结合时(此处说的是传值调用的情况,因为是传值调用嘛,所以实参的值不会变,所以传给函数的对象实际上是一份拷贝,当然如果是引用调用就宁当别论了)

3.如果函数的返回值是类的对象,函数执行完成返回给调用者时(因为在一个函数内的对象时局部对象,所以如果直接返回的话,他会消散的,这和我们c中的局部变量的性质是一样的,所以在返回时,其实返回的是局部对象的拷贝)

0x6类的组合

接下来还要说说类的组合,也就是一个类的定义中内嵌有其它类声明的对象,这种现象就是类的组合。关于类的组合有几个难点需要理解。

第一个难点:

当创建类的对象时,如果这个类具有内嵌对象成员,那么各个内嵌对象将首先被自动创建,因为部件对象是复杂对象的一部分,所以在创建对象时既要对本类的基本类型数据成员进行初始化,又要对内嵌对象成员进行初始化。这时,理解这些对象的构造函数的调用顺序就特别重要。所以组合类构造函数的定义的一般形式为:

类名::类名(形参表):内嵌对象1(对应形参),内嵌对象2(对应形参),....

对一个复杂对象进行初始化会依次调用他的内嵌对象的的构造函数进行相应的初始化,一般调用的顺序是按照内嵌对象在复杂对象中出现的次序进行调用的。上面说的是构造函数,有构造函数就一定有析构函数,析构函数调用的次序就和构造函数正好相反,至于为什么大家应该都可以想到,这里就不详述了。

#include <iostream>#include <cmath>using namespace std;//定义Point类class Point {public:Point(int xx = 0,int yy = 0){x = xx;y = yy;}Point(Point &p);  //声明复制构造函数int getX(){return x;}int getY(){return y;}private:int x,y;}//复制构造函数的定义Point::Point(Point &p){x = p.x;               y = p.y;cout<<"calling the copy construct!"<<endl;}//直接将元对象的两个属性复制给新的对象//类的组合class Line {public:Line(Point xp1,Point xp2);  //构造函数Line (Line &l);//复制构造函数double getLen(){return len;}private:Point p1,p2;    //Point类构造的两个对象   double len;}





原创粉丝点击