第十章 用户自定义类
10.1类的定义和使用
继承:通过对已有类增加新的数据或新的函数而派生新类的过程。
10.1.1counter类
抽象数据类型:组合了对该类型对象进行操作的一种数据类型。
counter类的详细说明
counter类的属性:
int count 计数值
int maxValue 计数值的最大值
counter类的成员函数:
increment 对计数值自增1
decrement 对计数值自减1
setCount 设置计数值
setMaxValue 设置最大值
getCount 返回计数值
getMaxValue 返回最大值
10.1.2counter类的定义
例子:counter类的定义
//计数器类定义
#ifndef COUNTER_H //用于避免多个定义
#define COUNTER_H //不属于类
class counter
{
public:
//成员函数
//构造函数
counter();
counter(int);
//增量计数器
void increment();
//递减计数器
void decrement();
//设置计数器值
void setCount(int);
//设置最大计数器值
void setMaxValue(int);
//返回当前计数器值
int getCount() const;
//返回最大计数器值
int getMaxValue() const;
private:
//数据成员(属性)
int count;
int maxValue;
}; //注意--类定义必须和分号
#endif //COUNTER_H
状态:由对象内部变量值来表示的该对象的当前状况。
公共部分(或类的接口):可以由其他程序组件进行访问的变量,数据类型,常量和函数的详细说明。
私有部分:只能由类的成员函数访问的变量,数据类型,常量和函数的详细说明。
类的头文件:包含类定义的扩展名为".h"的文件。
成员函数:在类的定义体内声明的函数。
数据成员:在类的定义中说明的变量,常量和数据类型。
10.1.3头文件counter.h中的编译预处理命令
头文件counter.h中前两行:
#ifndef COUNTER_H //用于避免多个定义
#define COUNTER_H //不属于类
类定义前的这些行可使编译器跳过文件中最后一行:
#endif //COUNTER_H
10.1.4使用counter类
例子:counter类的测试程序和用户的样例输出
//测试计数器类
#include "counter.h"
#include<iostream>
using namespace std;
int main()
{
counter c1; //计数器最大值INT_MAX类型的变量
counter c2(10); //计数器最大值 10 类型的变量
//测试集计数、递增、递减和获取计数
//作用域
c1.setCount(50); //c1 到 50 的设定值
c1.decrement();
c1.decrement();
c1.increment();
cout<<"Final value of c1 is "<<c1.getCount()<<endl;
c2.increment();
c2.increment();
c2.decrement();
cout<<"Final value of c2 is "<<c2.getCount()<<endl;
return 0;
}
10.1.5文件counterTest.cpp中的编译预处理命令
10.2类的实现
实现文件:提供类中成员函数c++代码的扩展名为cpp的文件。
作用域解析运算符:在定义类的成员函数时,位于函数名和类名之间的运算符。
例子:counter类的实现文件
//计数器类实现
#include "counter.h"
#include<iostream>
#include<climits> //对于INT_MAX
using namespace std;
//默认构造函数
counter::counter()
{
count=0;
maxValue=INT_MAX; //将最大值设置为默认最大值
}
//带参数的构造函数
counter::counter(int mVal) //输入:最大整数值
{
count=0;
maxValue=mVal; //将最大值设置为 mVal
}
//增量计数器
void counter::increment()
{
if(count<maxValue)
count++;
else
cerr<<"Counter overflow.Increment ignored."<<endl;
}
//递减计数器
void counter::decrement()
{
if(count>0)
count--;
else
cerr<<"Counter underflow.Decrement ignored."<<endl;
}
//设置计数器值
void counter::setCount(int val)
{
if(val>=0&&val<=maxValue)
count=val;
else
cerr<<"New value is out of range.Value not changed."<<endl;
}
//设置最大计数器值
void counter::setMaxValue(int val)
{
if(val>=0&&val<=INT_MAX)
maxValue=val;
else
cerr<<"New maxValue is out of range-not changed."<<endl;
}
//得到当前计数器值
int counter::getCount() const
{
return count;
}
//得到最大计数器值
int counter::getMaxValue() const
{
return maxValue;
}
10.2.1构造函数
构造函数:定义类的对象时自动执行的成员函数,构造函数用来设置新对象的初始状态。
10.2.2访问器和修改器函数
修改器:修改数据成员值的成员函数。
访问器:返回数据成员值的成员函数。
10.2.3文件counter.cpp中的编译预处理命令
程序员必须将#include “counter.h” 放在两个文件中,以便编译这些文件时,c++能够访问类的定义。
10.3类和对象的使用规则总结
10.3.1对象作为类的实例
变量:我们把基本数据类型,枚举,数组和结构体类型的名字。
对象:把类构造函数定义的名字。
10.3.2公有访问和私有访问
客户端:使用另一个预定义类的程序组件。
服务器:一种为其他程序组件提供操作的程序组件(通常是一个类),使它们能够操作服务器的数据。
10.3.3类和成员函数定义的语法
类的定义
格式:class类名
{
public:
1)类属性的列表(变量,数据类型,常量等),可由类外进行访问
2)成员函数的函数原型列表,可由类外通过函数名进行访问
.......
private:
1)类属性的列表(变量,数据类型,常量等),在类外是隐式的
2)成员函数的函数原型列表,在类外是隐式的
......
}; //不要忘记分号
例子:class checkingAccount
{
public:
//成员函数...
//把存款存入常用账户
void makeDeposit
(int); //输入:接收存款的账户
//设置账目的服务费用
void setServiceCharge(int ,float );
private:
//数据成员
char initFirst,initMiddle,initLast; //初始值
int accountNum; //账户
float balance; //账户余额
float serviceCharge; //服务费用
}; //不要忘记分号
说明:所有类的成员函数都可以访问类定义体中的函数,变量,数据类型和常量,但是只有声明为public的成员才能在类外进行访问。
类的成员函数定义
格式:数据类型 类名::成员函数名
(形式参数列表)
{
...
函数体
...
}
例子://构造函数
checkingAccount::checkingAccount()
{
accountNum=0;
balance=0.0;
}
//把存款存入常用账户
void checkingAccount::makeDeposit(int acNum) //输入:接收存款的账户
{
//局部数据...
float amount;
//存款
if(accountNum==acNum)
{
balance+=amount;
}
else
cout<<"Wrong account number specified."<<endl;
}
说明:makeDeposit函数是checkingAccount类的成员函数,该函数可以访问类的所有数据成员和函数成员,除此之外,和其他的C++函数一样的。为了确保C++编译器能够知道该函数和类有关,需要在函数名前加上"类名::"
提示:类的成员函数能够直接访问类的所有数据成员(变量,常量等)。
10.3.4结构体和类的比较
相同点:(1)都是相关数据元素相组合的一种数据类型,这些元素可能具有不同的数据类型。
(2)都包含函数原型的声明。
(3)都可以对函数和数据指定三种不同级别的访问控制:public,protected和private.
不同点:结构体成员的默认访问控制属性是public,而类成员的默认访问控制属性是private.
10.3.5工程文件和独立编译
10.3.6数组,结构体和类的组合
10.3.7函数重载和多态性
函数重载:对一个特定的函数提供不同的形式参数列表。
多态性:根据函数所应用的对象不同以及不同的实参列表从而调用不同操作的函数的能力。
10.4类对象作为操作数和参数
运算符重载:多个类的对象使用同一个运算符的能力。
例子:compareCounter函数
int counter::compareCounter(const counter& aCounter) const
{
int result;
if(count<aCounter.count)
result=-1;
else if(count==aCounter.count)
result=0;
else
result=1;
return result;
}
10.5fraction类
10.5.1fraction类的设计
fraction类的详细说明
fraction类的属性:
int num 分数的分子
int denom 分数的分母
fraction类的成员函数
fraction 构造函数
setNum 设置分子
setDenom 设置分母
multiply 分数乘法
divide 分数除法
add 分数加法
subtract 分数减法
readFrac 输入分数
displayFrac 显示分数
getNum 返回分子
getDenom 返回分母
例子:fraction类的定义
//分数类定义
#ifndef FRACTION_H
#define FRACTION_H
class FRACTION_H
{
public:
//成员函数
//构造 函数
fraction();
fraction(int);
fraction(int, int);
//设置分子和分母
void setNum(int);
void setDenom(int);
//乘以分数
fraction multiply(fraction f1);
//除以分数
fraction divide(fraction f1);
//加分数
fraction add(fraction f1);
//分数减法
fraction subtract(fraction f1);
//读一个分数
void readFrac();
//显示一个分数
void displayFrac() const;
//访问
int getNum() const;
int getDenom() const;
private:
//数据成员(属性)
int num;
int denom;
};
#endif // FRACTION_H
10.5.2使用fraction类
例子:测试fraction类的驱动函数
//测试分数类。
#include<iostream>
#include "fraction.h"
using namespace std;
int main()
{
fraction f1,f2; //输入-分数操作数
fraction f3; //输出-操作结果
//读取两个分数
cout<<"Enter 1st fraction:"<<endl;
f1.readFrac();
cout<<"Enter 2nd fraction:"<<endl;
f2.readFrac();
//显示分数运算的结果
f3=f1.multiply(f2);
f1.displayFrac(); cout<<"*";
f2.displayFrac(); cout<<"=";
f3.displayFrac(); cout<<endl;
f3=f1.divide(f2);
f1.displayFrac(); cout<<"/";
f2.displayFrac(); cout<<"=";
f3.displayFrac(); cout<<endl;
f3=f1.add(f2);
f1.displayFrac(); cout<<"+";
f2.displayFrac(); cout<<"=";
f3.displayFrac(); cout<<endl;
f3=f1.subtract(f2);
f1.displayFrac(); cout<<"-";
f2.displayFrac(); cout<<"=";
f3.displayFrac(); cout<<endl;
return 0;
}
10.5.3fraction类的实现文件
例子:fraction类的实现文件
//分数类实现
#include "fraction.h"
#include<iostream>
using namespace std;
//成员函数
//构造 函数
fraction::fraction()
{
num=0;
denom=1;
}
fraction::fraction(int n)
{
num=n; //整数的分数
denom=1;
}
fraction::fraction(int n,int d)
{
num=n;
denom=d;
}
//设置分子和分母
void fraction::setNum(int n)
{
num=n;
}
void fraction::setDenom(int d)
{
denom=d;
}
//乘以分数
fraction fraction::multiply(fraction f)
{
fraction temp(num * f.num,denom * f.denom);
return temp;
}
//除以分数
fraction fraction::divide(fraction f)
{
fraction temp(num * f.denom,denom * f.num);
return temp;
}
//加以分数
fraction fraction::add(fraction f)
{
fraction temp(num * f.denom+ f.num * denom,denom * f.denom);
return temp;
}
//减去分数
fraction fraction::subtract(fraction f)
{
fraction temp(num * f.denom - f.num * denom,denom * f.denom);
return temp;
}
//读取分数
void fraction::readFrac()
{
char slash; //存储"/"
do{
cout<<"Enter numerator / denominator: ";
cin >> num >> slash >> denom;
}
while(slash !='/');
}
//显示分数
void fraction::displayFrac() const
{
cout<<num<<'/'<<denom;
}
//访问
int fraction::getNum() const
{
return num;
}
int fraction::getDenom() const
{
return denom;
}
10.6circle类
10.6.1circle类的设计
circle类的详细说明
circle类的公有数据类型:
color 具有8个颜色值的枚举类型
circle类的属性:
int x x坐标
int y y坐标
float radius 半径
color cColor 颜色
float area 面积
float perimeter 周长
circle类的成员函数:
circle 构造函数
setCoord 设置x和y坐标值
setRadius 设置圆的半径
setColor 设置圆的颜色
computeArea 计算圆的面积:area=pi*radius*radius
computePerimeter 计算圆的周长:perimeter=2.0*pi*radius
displayCircle 显示圆的属性
getX 返回x坐标值
getY 返回y坐标值
getColor 返回圆的颜色
getArea 返回圆的面积
getPerimeter 返回圆的周长
例子:circle类的定义
//圆类定义
#ifndef CIRCLE_H
#define CIRCLE_H
class CIRCLE_H
{
public:
//枚举类型枚举颜色{黑色,蓝色,绿色,青色,红色,品红色,棕色,浅灰色,无色};
//成员函数
//构建函数
circle();
//设置中心坐标
void setCoord(int, int);
//设置半径
void setRadius(float);
//设置颜色
void setColor(color);
//计算面积
void computeArea();
//计算周长
void computePerimeter();
//显示属性
void displayCircle() const;
//访问器功能
int getX() const;
int getY() const;
float getRadius() const;
color getColor() const;
float getArea() const;
float getPerimeter() const;
private:
//数据成员(属性)
int x;
int y;
float radius;
color cColor;
float area;
float perimeter;
};
#endif // CIRCLE_H
10.6.2使用circle类
例子:测试circle类的驱动函数
#include "circle.h"
#include<iostream>
using namespace std;
int main()
{
circle myCircle;
//设置圆圈属性。
myCircle.setCoord(150,100);
myCircle.setRadius(10);
myCircle.setColor(circle::magenta);
//计算圆的面积和周长
myCircle.computeArea();
myCircle.computePerimeter();
//显示圆圈的属性
cout<<"The circle attributes follow:"<<endl;
myCircle.displayCircle();
return 0;
}