首页 > 代码库 > C++ Primer Plus的若干收获--(八)

C++ Primer Plus的若干收获--(八)

接下我会比较系统的介绍OOP的核心——类这个概念。可能会写的比较繁琐,比较多,但是自己理解总是好的。还记得上学期刚开始的时候老师讲的数据结构,一上来就来个LIst的一个大类,结果全班就傻了,完全不知所云(ps:博主是数学系,只学过C),然后自己就坐在图书馆借了两大本C++书开始啃了起来,大概啃了两个月才把C++学了个大概,尤其是读到类这块都是三四百行的常常的代码,看的那叫一个痛苦啊。不过自此之后就真正喜欢上这门语言了,再到之后能用C++写上个一两千行的代码,才发现之前的努力还是有收获的。好了,废话就说这么多了,下面进入正文。

 

8.1 OOP的特性

面向对象编程(OOP)是一种特殊的、设计程序的概念性方法。下面是其的一些重要的特性:

  • 抽象;
  • 封装和数据隐藏;
  • 多态;
  • 继承;
  • 代码的可重用性。

8.2 C++的类

类是将抽象转换为用户数据类型的C++工具,它将数据表示和操纵数据的方法组成一个整洁的包。下面我们先看一个表示股票的类接口

ifndef STOCKOO_H_#define STOCKOO_H_#include<string>class Stock{private:    std::string company;//公司名称    long shares;//所持股票的数量    double share_val;//每股的价格    double total_val;//股票总值    void set_tot(){total_val=shares*share_val;}public:    void acqure(const std::string&co, long n,double ptr);//获得股票    void buy(long num,double price);//增持    void sell(long num,double price);//卖出股票    void update(double price);//更新股票价格    void show();//显示关于所持的股票信息};#endif // STOCKOO_H_

比照这上面值得接口,下里面来介绍一下接口这个概念。对于类,我们说公共接口。在这里,公共是使用类的程序,交互系统有类的对象组成,而接口由编写类的人提供的方法组成。接口让程序员能够编写与类对象交互的代码,从而让程序能够使用类对象。比如,要计算string对象中包含多少个字符,您无需打开对象,而只需使用string类提供的四则()方法。类设计禁止公共用户直接访问类,但公众可以使用size()方法。


 

8.3 访问控制

 关键字public和private,它们描述了对类成员的访问控制。实用类成员的程序都可以直接访问公有成分,但是只能通过公有成员函数或者是友元函数来访问对象的私有成员。因此,公有成员函数是程序和对象的私有成员之间的桥梁,提供了对象和成员之间的接口。

类设计尽可能地将公有接口与实现的细节分开。公有接口表示抽象的组件。将实现细节放在一起并将它们与抽象分开被称为封装。数据隐藏是一种封装,将实现的细节隐藏在私有部分中。

 

8.4 类的构造函数和析构函数

上述的接口并不完整,还需要一些补充,没错就是缺少构造函数与析构函数

int year=2001;//validstruct thing{  char* pn;  int m;};thing amabob={"aodget",-23};//validStock hot={"sasd.Inc",200,50.1};//NO!compile error

不能像上面初始化的原因在于,数据部分的状态是私有的,这意味着程序不能直接访问数据成员。程序只能通过成员函数来访问数据成员,因此要设计合适的成员函数才能将其初始化。我们下面来看一下一种可能的构造函数的定义

Stock::Stock(const string& co,long n,double pr){  compary=co;  if(n<0)  {    std::cerr<<"Number of shares can't be negative;"<<company<<"shares set to 0.";    shares=0;  }else     shares=n;  shares_val=pr;  set_tot();}

之后我们可以用两种使用该构造函数的方式来初始化对象。第一种是显式的调用构造函数

Stock food=Stock("World Cabbage",250,1.25);

另一种是隐式的调用构造函数

Stock garment("Furry Mason",50,2.5);

另外构造函数还可以和new操作符一起使用

Stock *pstock=new Stock("Electroshock Games",18,19.0);


接下来我们再来看构造函数——默认构造函数

Stock::Stock(){}Stock fluffy;//use the defalt constructor


默认构造函数没有参数,因为声明中不包含值。奇怪的是,当且仅当没有定义任何构造函数时,编译器才会提供默认构造函数。为类定义了构造函数后,程序员就必须为它提供默认构造函数。如果提供了非默认构造函数,但没有提供默认构造函数,则下面的声明则会出错:

Stock Stock1;//error

在创建了默认构造函数后,便可以声明对象变量,而不必对其进行初始化

Stock first;//calls defalt constructorStock first=Stock();//calls is explicitlyStock *prilief=new Stock;//calls it implicitly


之后我们再来看一下另一个特殊的成员函数——析构函数。当对象过期是,系统会自动的调用析构函数,其通常完成清理工作,实际上很有用。比如,如果构造函数使用new来分配内存,则析构函数则用delete来释放这些内存。下面为Stock提供了一个析构函数

Stock::~Stock(){}

与构造函数不同的是,析构函数没有参数。

 

8.6 改进的Stock类

ifndef STOCKOO_H_#define STOCKOO_H_#include<string>class Stock{private:    std::string company;//公司名称    long shares;//所持股票的数量    double share_val;//每股的价格    double total_val;//股票总值    void set_tot(){total_val=shares*share_val;}public:   Stock(const std::string& co,long n=0,double pr=0.0);   Stock();        void acqure(const std::string&co, long n,double ptr);//获得股票    void buy(long num,double price);//增持    void sell(long num,double price);//卖出股票    void update(double price);//更新股票价格    void show() const;//显示关于所持的股票信息};#endif // STOCKOO_H_我们应该注意一下const成员函数,这种语法保证函数不会修改调用的函数对象。以这种方式定义和声明的类函数被称为const成员函数。就像应该尽可能将const引用和指针用作函数形参一样,只要类方法不修改调用的对象,就应该将其声明为const。从现在开始,我们将遵守这一原则。</span>


8.7 this指针

假设我们要给Stock类增加一个成员函数,要其对stock1与stock2进行比较,并将其中股价较高的那个赋给top对象。则我们需啊哟如下的代码来完成

const stock& Stock::topval(const Stock& s)const{  if(s.total_val>total_val)     return s;  else     return *this;}//返回类型会引用意味着调用为返回对象本身,而不是气副本

注意这个被称为this的特殊指针。它被用来调用成员函数的对象(this被称为隐藏参数传递方法)。这样,函数调用stock1.topval将this设置为stock1对象的地址。一般来说,所有类方法豆浆this指针设置为调用它的对象的地址。却是,topval()中的total_val只不过是this->total_val的简写。

另外,需要注意的是每个成员函数都有一个this指针。this指针指向调用的对象。如果方法需要引用整个调用对象,则可以使用*this。在上述函数使用const限定符将this限定为const,这样将不能使用this来写该对象的值。然而,要返回的并不是this,因为this是对象的地址,而*this则是对象本身。


 

好了,这次就写到这里吧。突然想到好几天没有玩游戏了,果断跑出去玩两把啊。上帝要原谅我的贪玩啊。。。