今天开始正式步入C++的OOP世界,之前是python的OOP世界
前言
面向对象编程(OOP)是一种特殊的、设计程序的概念性方法,C++通过一些特性改进了C语言,使得应用这种方法更容易。下面是最重要的OOP特性:
- 抽象
- 封装和数据隐藏
- 多态
- 继承
- 代码可重用
为了实现这些特性并将它们组合在一起,C++所做的最重要的改进是提供了类
。本章将讨论如何定义类、如何为类提供公有部分和私有部分以及如何创建使用类数据的成员函数。另外,还将介绍构造函数和析构函数,它们是特殊的成员函数,用于创建和删除属于当前类的对象。最后介绍this指针,对于有些类编程而言,它是至关重要的。
构造类接口
为开发一个类并编写一个使用它的程序,需要完成多个步骤。这里将开发过程分成多个阶段
,而不是一次性完成。通常,C++程序员将接口(类定义)放在头文件中
,并将实现放在源代码文件中
。这里采用这种典型做法。下面是第一个阶段的代码,它是Stock类的类声明。
#ifndef STOCK00_H_
#define STOCK00_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 acquire(const std::string & co, long n, double pr);
void buy(long num, double price);
void sell(long num, double price);
void update(double price);
void show();
};
首先,C++关键字class指出这些代码定义了一个类设计,这种语法指出,Stock是这个新类的类型名。该声明让我们能够声明Stock类型的变量——称为对象或实例。
访问控制
关键字private和public也是新的,它们描述了对类成员的访问控制。使用类对象的程序都可以直接访问公有部分,但只能通过公有成员函数(或友元函数,后面会介绍)来访问对象的私有成员。例如,要修改Stock类的shares成员,只能通过Stock的成员函数。因此,公有成员函数是程序和对象的私有成员之间的桥梁,提供了对象和程序之间的接口。防止程序直接访问数据被称为数据隐藏。
类设计尽可能将公有接口与实现细节分开
。公有接口表示设计的抽象组件。将实现细节放在一起并将它们与抽象分开被称为封装。数据隐藏(将数据放在类的私有部分中)是一种封装
,将实现的细节隐藏在私有部分中,也是一种封装
。封装的另一个例子是,将类函数定义和类声明放在不同的文件中。
控制对成员的访问
无论类成员是数据成员还是成员函数,都可以在类的公有部分或私有部分中声明它。但由于隐藏数据是OOP主要的目标之一,因此数据项通常放在私有部分,组成类接口的成员函数放在公有部分
;否则,就无法从程序中调用这些函数。正如 Stock 声明所表明的,也可以把成员函数放在私有部分中。不能直接从程序中调用这种函数,但公有方法却可以使用它们。通常,程序员使用私有成员函数来处理不属于公有接口的实现细节。
不必在类声明中使用关键字private,因为这是类对象的默认访问控制然而,为强调数据隐藏的概念,最好显式地使用了private。
类描述看上去很像是包含成员函数以及public和private可见性标签的结构声明。实际上,C++对结构进行了扩展,使之具有与类相同的特性。它们之间唯一的区别是,结构的默认访问类型是 public,而类为private。
C++程序员通常使用类来实现类描述,而把结构限制为只表示纯粹的数据对象。
实现类成员函数
还需要创建类描述的第二部分
:为那些由类声明中的原型表示的成员函数提供代码。成员函数定义与常规函数定义非常相似,它们有函数头和函数体,也可以有返回类型和参数。但是它们还有两个特殊的特征:
- 定义成员函数时,使用作用域解析运算符(::)来标识函数所属的类;
- 类方法可以访问类的private组件。
首先,成员函数的函数头使用作用域运算符解析(::)来指出函数所属的类。例如,update( )成员函数如下:
void Stock::update(double price)
{
...
}
编写类成员函数除了多了一个类名和作用域解析符外,其余是一样的。
定义位于类声明中的
函数都将自动成为内联函数,因此 Stock::set_tot( )是一个内联函数。类声明常将短小的成员函数作为内联函数,set_tot( )符合这样的要求。
所创建的每个新对象都有自己的存储空间,用于存储其内部变量和类成员;但同一个类的所有对象共享同一组类方法,即每种方法只有一个副本。
总结
指定类设计的第一步是提供类声明
。类声明类似结构声明,可以包括数据成员和函数成员。
声明有私有部分,在其中声明的成员只能通过成员函数进行访问;声明还具有公有部分,在其中声明的成员可被使用类对象的程序直接访问。通常,数据成员被放在私有部分中,成员函数被放在公有部分中,
因此典型的类声明的格式如下:
class className
{
private:
data member declarations;
public:
member function prototypes;
}
公有部分的内容构成了设计的抽象部分——公有接口。将数据封装到私有部分中可以保护数据的完整性,这被称为数据隐藏。因此,C++通过类使得实现抽象、数据隐藏和封装等OOP特性很容易。
指定类设计的第二步是实现类成员函数。可以在类声明中提供完整的函数定义,而不是函数原型,但是通常的做法是单独提供函数定义(除非函数很小)。在这种情况下,需要使用作用域解析运算符来指出成员函数属于哪个类。例如,假设Bozo有一个名为Retort( )的成员函数,该函数返回char指针,则其函数格式如下所示:
char *Bozo::Retort()
{
...
}