面向对象编程(OOP)是一种特殊的、设计程序的概念性方法。为了更好地实现这种方法,C++引入了类。类是创建对象的模板,用代码描述一类事物的共同特征(属性)和行为(方法)。
过程性编程与面向对象编程
顾名思义,前者注重步骤顺序,后者注重对象协作(谁做什么)。下面将通过一个日常的例子加以区分。
例如在生活中,对于我将食物放进冰箱这一事件,面向过程思想会按照顺序思考:拿起食物,打开冰箱,放入食物,关闭冰箱;而面向对象思想则会首先考虑参与事件的对象并划分职责:人的操作有拿起食物,放入食物,冰箱的操作有打开,关闭和贮存食物。接下来考虑对象间的交互,人对象触发与冰箱的交互,使得冰箱进行相应操作。各个对象各司其职,并在相互交互中共同完成事件。
定义类
一般来说,类规范由两个部分组成:
- 类声明:以数据成员的方式描述数据部分,以成员函数的方式描述公有接口。
- 类方法定义:描述如何实现类成员函数。
将实现细节放在一起并将它们与抽象的公有接口分开被称为封装。
根据上述例子,下面先实现一个类声明
//refri.h
#ifndef N//避免重复包含头文件
#define N
#include<cstdbool>
#include<iostream>
#include<vector>
#include<string>
using Food=std::string;
class refrigerator{
private:
bool isopen=false; //私有属性:门状态
std::vector<Food> storedfood; //私有属性:存储的食物
public:
//公有方法:定义冰箱的行为接口
void openDoor();
void closeDoor();
void storeFood(const Food& item);
}
#endif
首先class关键字指出这些代码定义了一个类设计,refrigerator是一个新类的类型名。该类型的实例称为对象。
refrigerator a;
refrigerator b;
//创建了两个对象,都属于冰箱类
关键字private和public描述了对类成员的访问控制。使用类对象的程序都可以直接通过对象访问公有部分,但只能通过公有成员函数(或友元函数)来访问对象的私有成员。
注意:在C++中对结构进行了扩展,使之具有与类相同的特性。它们之间唯一的区别是结构的默认返回类型是public,而类的为private(因此类声明中的private关键字是可以省略的)。
下面进行实现类描述的第二部分
//refri.cpp
#include<iostream>
#include"refri.h"
void refrigerator::openDoor(){
if(!isopen){ //避免重复开门
isopen=true;
std::cout<<"冰箱门已打开"<<std::endl;
}
}
void refirgerator::closeDoor(){
if(isopen){
isopen=false;
std::cout<<"冰箱门已关闭"<<std::endl;
}
}
void refrigerator::storeFood(const Food& item){
if(ifopen){
storedFood.push_back(item);
std::cout<<"食物已放入冰箱"<<std::endl;
}
}
可见成员函数的定义有两点特性:
- 定义成员函数时需用作用域解析运算符(::)来标识函数所属的类。
- 类方法可以访问类的private成员。该例中直接访问了storedFood和isopen成员。
特殊地,可以将成员函数变成内联函数。、
class refrigerator{
private:
bool isopen=false; //私有属性:门状态
std::vector<Food> storedfood; //私有属性:存储的食物
void openDoor(){
if(!isopen){
isopen=true;
std::cout<<"冰箱门已开启"<<std::endl;
}
public:
//公有方法:定义冰箱的行为接口
void closeDoor(){
if(isopen){
isopen=false;
std::cout<<"冰箱门已关闭"<<std::endl;
}
void storeFood(const Food& item);
}
在类声明中定义的函数都将自动变成内联函数,而类声明外的得内联函数则需要使用inline限定符
inline void refrigetator::closeDoor(){
if(isopen){
isopen=false;
std::cout<<"冰箱门已关闭"<<endl;
}
}
但内联函数的特殊规则要求每个使用它们的文件都对其定义,因此最简便的方法是将内联定义放在头文件中。
使用对象
对象通过使用成员运算符来调用类方法
refrigerator a;
a.openDoor;//对象调用类方法
注;新对象都有自己的存储空间,用于存储其内部变量和类成员(各自的数据),但同一类的所有对象共享同一组方法,即每种方法只有一个副本。