本章内容包括:
- 过程性编程和面向对象编程
- 类概念
- 如何定义和实现类
- 共有类访问和私有类访问
- 类的数据成员
- 类方法(类函数成员)
- 创建和使用类对象
- 类的构造函数和西沟函数
- const成员函数
- this指针
- 创建对象数组
- 类作用域
- 抽象数据类型
面向对象编程(OOP)是一种特殊的、设计程序的概念性方法,C++ 通过一些特性改进了C语言,使得应用这种方法更容易。下面是最重要的OOP特性:
- 抽象;
- 封装和数据隐藏;
- 多态;
- 继承;
- 代码的可重用性。
10.1 过程性编程和面向对象编程
采用OOP方法时:
- 描述对象所需的数据以描述用户与数据交互所需的操作;
- 确定如何实现接口和数据存储
10.2 抽象和类
10.2.1 类型是什么
抽象:
类表示人们可以用类方法的公有接口对类对象执行操作,这是抽象;
抽象是通往用户定义类型的捷径,C++中用户定义类型是实现抽象接口的类设计
数据隐藏:
类的数据成员可以是私有的(默认值),这意味着只能通过成员函数来访问这些数据,这是数据隐藏
封装:
实现的具体细节(如数据表示和方法的代码)都是隐藏的,这就是封装
类型:
- 决定数据对象需要的内存数量
- 决定如何解释内存中的位(long 和 float 在内存中占用的位数相同,但将他们转换为数值的方法不同)
- 决定可使用数据对象执行的操作和方法
10.2.2 C++中的类
类规范由两部分组成:
类声明: 以数据成员的方式描述数据部分,以成员函数(方法的方式描述公接口
类方法定义: 描述如何实现类成员函数
简单地说,类声明提供了类的蓝图,而方法定义提供了细节
什么是接口:
接口是一个共享框架,供两个系统交互时使用;
接口让程序员能编写与类对象交互的代码,从而让程序能够使用类对象
类声明:
#include#includeclass Stock{private: char company[30]; int shares; double share_val; double total_val; void set_tot() { total_val = shares * share_val; }public: void acquire(const char*co, int n, double pr); void buy(int num, double price); void sell(int num, double price); void update(double price); void show();};
关键字 class 指出这些代码定义了一个类设计;
Stock 成为一个新的类型名,能够声明 Stock 类型的变量,称为对象或实例:Stock sally; // 创建 Stock 对象 sallyStock solly; // 创建 Stock 对象 solly
关键字 private 和 public 描述了对类成员访问控制:
使用类对象的程序都可以直接访问共有部分;
只能通过共有成员函数访问对象的私有成员;
共有成员函数提供了对象和程序之间的接口;
防止程序直接访问数据被称为数据隐藏:
数据隐藏(将数据放在类的私有部分中)是一种封装;
封装的另一个例子,将类函数定义和类声明放在不同的文件中
数据项通常放在私有部分,组成类接口的成员函数放在共有部分;
不必在类声明中使用关键字 private,因为这是类对象的默认访问控制
10.2.3 实现类成员函数
类成员函数定义特征:
- 定义成员函数时,使用作用域解析操作符(::)来标识函数所属的类
- 类方法可以访问类的 private 组件
将类声明放在头文件中,而将类成员函数定义放在单独的一个源代码文件中;
定义位于类声明中的函数都将自动成为内联函数;
调用成员函数时,他将使用被调用他的对象的数据成员:
所创建的每个新对象都有自己的存储空间,用于存储其内部变量和类成员;
同一个类的所有对象共享同一组类方法,即每种方法只有一个副本
10.2.4 使用类
C++ 的目标是使得使用类与使用基本的内置类型尽可能相同:
要创建类对象,可以声明类变量,也可以使用 new 为类对象分配存储空间;
可以把对象作为函数的参数和返回值,也可以将一个对象赋给另一个对象
使用新类型,最关键的是要了解成员函数的功能,而不必考虑实现的细节
10.2.5 小结
类设计:
1. 提供类声明
class className{private: data member declarations // 将数据放私有部分中可以保护数据的完整性,数据隐藏public: member function prototypes};
2. 实现类成员函数
3. 类成员函数(方法)通过类对象调用
Bozo bozetta;cout << Bozetta.Retort();
实现文件:
stock1.h 文件提供类声明:
#ifndef STOCK1_H_#define STOCK1_H_class Stock{private: char company[30]; int shares; double share_val; double total_val; void set_tot() { total_val = shares * share_val; }public: Stock(); Stock(const char *co, int n = 0, double pr = 0.0); ~Stock(); void buy(int num, double price); void sell(int num, double price); void update(double price); void show();};#endif
stock1.cpp 文件实现了类成员函数的定义
#include#include "stock1.h"Stock::Stock(){ std::cout << "Default constructor called"; std::strcpy(company, "no name"); shares = 0; share_val = 0.0; total_val = 0.0;}Stock::Stock(const char *co, int n, double pr){ std::cout << "Constructor using " << co << " called"; std::strncpy(company, co, 29); company[29] = '0'; if (n < 0) { std::cerr << "Number of shares can`t be negative; " << company << " shares set to 0."; shares = 0; } else { shares = n; share_val = pr; set_tot(); }}Stock::~Stock(){ std::cout << "Bye, " << company << "!";}void Stock::buy(int num, double price){ if (num < 0) { std::cerr << "Number of shares purchased can`t be negative. " << "Transaction is aborted."; } else { shares += num; share_val = price; set_tot(); }}void Stock::sell(int num, double price){ using std::cerr; if (num < 0) { std::cerr << "Number of shares purchased can`t be negative. " << "Transaction is aborted."; } else if (num > shares) { cerr << "You can`t sell more than you have! " << "Transaction is aborted."; } else { shares -= num; share_val = price; set_tot(); }}void Stock::update(double price){ share_val = price; set_tot();}void Stock::show(){ std::cout << "company: " << company << " shares: " << shares << std::endl << " share price: $" << share_val << " Total Worth: $" << total_val << std::endl;}
usestock1.cpp 文件测试
#include#include "stock1.h"int main(){ using std::cout; using std::ios_base; cout.precision(2); cout.setf(ios_base::fixed, ios_base::floatfield); cout.setf(ios_base::showpoint); cout << "Using constructors to ctreat new objects"; Stock stock1("NanoSmart