《C++ Primer Plus》《10、对象和类》

前言:

面向对象编程(OOP)这是一种特殊的,设计程序的概念性方法,下面是他的一些特性:

  • a.抽象
  • b.封装和数据隐藏
  • c.多态
  • d.继承
  • e.代码的可重用性

C++与C最大的区别就是提出了类,以上的特点都是通过类来展开的,这一章将重点介绍“类”这个重要概念。

1 过程性编程和面向对象编程

所谓过程性编程是从代码实现的角度,来进行编程,用多个函数来解决复杂的问题;而面向对象编程,首先从用户的角度来考虑对象,描述对象所需的数据,以及描述用户与数据交互的操作。完成对接口的描述后,需要确定如何实现接口和数据存储。最后,创建出程序,这便是C++相对于C的进步。
这样说有点晦涩,举个例子,你是个仓库管理员,仓库里放满了车子,你想编个程序进行管理,用C如何实现,我会用main()函数调用一个函数来获取输入,调用另一个函数,对车子停车时长进行计算,用第三个函数来显示结果;这些只是对数据的处理,我们后续还要进行增删查改,以及对数据的存储,还要创建另外的数组。这种方法太过死板;如果C++出马,首先他会创建一个对象记录车的各个数据,还要考虑如何处理这些数据,这样后续进行增删查改也更加灵活方便。

2 抽象和类

实际要解决的问题千奇百怪,最好的解决方法是化繁为简,以不变应万变。简单和抽象是解决复杂性问题的主要方法,即将问题的本质抽象出来,根据问题的特征来解决问题。

2.1 类型是什么

类型,比如定义你的理想型,肤白貌美,有钱,这是特性的描述,有人喜欢说话声音轻柔的,善解人意的,这就是你理想型的行为特征,所以类不仅有数据成员,还有方法成员。

2.2 C++中的类

在C++中类不仅是一个概念,更是一种解决问题的工具,它将数据表示和操纵数据的方法组合成一个完整的包。书中用一个表示股票的类,类中有2个部分:
1)股票信息:公司名称,股票数量等;
2)操作信息:增持,抛售股票等;
总结一下,类声明提供了类的蓝图,方法定义了实现的细节。

  • a.访问控制
    在类的声明中有两个关键字,private与public,描述了对类成员的访问控制。使用类对象的程序只能访问public部分,但只能通过公有成员函数来访问对象的私有成员。
  • b.控制对成员的访问:
    一般来说方法,成员函数的权限是private, 组成类接口的成员函数放在公有部分,其他成员都可以调用公用的接口。C++出于数据隐藏的目的,其他类成员只能通过类接口来访问类成员,否则无法进行访问。

2.3 实现类成员函数

通常在一个头文件中对类进行声明,而其中类的接口的实现在另一个源文件中实现,书中的示例就是将类方法全部写在另一个源文件中。详见股票程序。
在这里插入图片描述

2.4 使用类

在头文件中定义了类,并在一个源文件中定义了类接口的实现方法,接着就是在主函数中对类进行调用了,书中usestock00.cpp对类进行了调用,验证了程序的正确性。

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

类被设计出来有一个初衷:隐藏数据!所以数据部分的访问状态是私有的,这样程序就不能直接访问数据成员。为此,C++专门提供了一类特殊的成员函数——类构造函数,专门用于构造新对象,将数值赋予给他们的成员。而析构函数与构造函数的功能相反,实在程序的生命周期结束的时候,将他们的成员置空删除。

3.1 声明和定义构造函数

构造函数的声明种有一些形参,这些形参表示的不是类成员,而是要赋予给类成员的数值,要注意区别参数名与类成员名,为了做区分,通常将类成员名加上m_的前缀。

3.2 使用构造函数

创建了类之后,需要用构造函数,对类对象赋予初始值,赋予初始值有两个方法,
方法一:显示地调用

Stock A = Stock(“A”,1,1.0);

方法二:隐式地调用

Stock B(“B”,2,2.0);

3.3 默认构造函数

所谓默认的构造函数,就是未提供显式初始值时,用来创建对象的构造函数。在程序中当且仅当没有定义任何构造函数时,编译器才会提供默认构造函数。如果提供了非默认的构造函数,直接声明类对象会出错。
例如:

Stock(const char* co,int n,double pr)
Stock stock1

此时,声明的stock1就会出错。
除了不写构造函数,有2种方法可以构造默认函数,以上述的Stock为例子。
方法一:给已有的构造函数的所有参数提供默认值

Stock(const string &co = “Error”,int n = 0,double pr = 0.0);

方法二:通过函数重载来定义一个构造函数

Stock::Stock(){
	company = “error”;
	shares = 0;	
	share_val = 0.0;
	total_val = 0.0;
}

3.4 析构函数

用构造函数创建对象后,程序负责跟踪对象,直到其过期为止。对象过期时,程序会自动调用一个特殊的成员函数,负责完成清理工作。析构函数与构造函数同名,但是函数之前加上了一个~以作区分。析构函数内不需要做任何事情,要是没有写析构函数,程序会提供一个默认的析构函数。

4 this指针

每个类成员都只涉及一个对象,当涉及两个对象时,就需要使用C++的this指针。这个概念类似于我之前学习python的self函数代指自身。
书中有一个示例:topval()方法用来比较两个股票的总价,比较方法的原型是:

const Stock & topval(const Stock & s) const;

将其中股价较高的那一支股票赋值给top,

top = stock1.topval(stock2);

这个函数隐式地访问stock1,显示地访问stock2,此时就会发现,你只能返回引用的s,以上智能返回stock2,而不能返回stock1,C++提供了解决这种问题的方法——this指针,this被作为隐藏参数传递给方法。
补充:每个成员函数(包括构造函数和析构函数)都有一个this指针,this指针指向调用对象,如果方法需要引用整个调用对象,则可以使用表达式*this。

5 对象数组

在实际应用中,用户通常要创建同一个类的多个对象,这些对象又都属于同一个类,这就类似于“数组“的概念。这个时候需要显示地调用构造函数,将对象的参数都输入进去。
举个例子:

const int len = 4;
Stock stocks[len]={
	Stock(“A”,1,1),
Stock(“B”,2,2),
Stock(“C”,3,3),
Stock(“D”,4,4),
};

6 类的作用域

在类中定义的名称的作用域为整个类,作用域为整个类的名称只是在该类中是已知的。所以在不同类中使用相同的类成员名不会引起冲突。

6.1 作用域为类的常量

在类中如果要声明一个常量,直接const int x = 10;这样是不行的,在声明类中只是描述了对象的形式,并没有创建对象,所以在创建对象之前没有用于存储数值的空间。有2种方法可以实现常量的声明
1)在类中声明一个枚举:

class Barkey{
private:
			enum{Months = 12};
			double const[Months];
			……}

2)用static定义常量:

class Barkey{
private:
			static const int Months = 12;
			double const[Months];
			……}

6.2 作用域内枚举

传统的枚举可能存在一些问题,例如enum A {S,M,X,XL} enum B{S,M,X,L},这两个枚举量就存在冲突。为了避免这种冲突,C++11提供了一种新枚举,其枚举量的作用域为类。

enum  class  A {S,M,X,XL}enum  class  B{S,M,X,L}

引用的时候就添加A::S,这样就能避免冲突。

7 抽象数据类型

书中举了一个卖股票的例子,这个stock类十分的具体,有股票的各种信息,也包含了对股票的各种操作。但是程序员也会用类表示抽象数据类型(Abstarct data type)。书中用类来对栈进行描述。见书中程序清单。

8 总结

首先,提供了类这个概念,私有数据成员存储信息,公有成员函数提供访问数据的唯一途径,类将数据和方法合成了一个单元,私有数据成员实现了数据隐藏。
另外介绍了两个十分重要的函数构造函数与析构函数,用来创建与销毁类,并介绍了默认的构造与析构函数。
希望成员对多个类进行应用,介绍了this的概念,用this指针设置成调用对象的地址,*this是该对象的别名。

9 参考

9.1 《C++ Primer Plus》

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值