设计一个程序,其中有3个类CBank、BBank、GBank,分别为中国银行类,工商银行类和农业银行类。每个类都包含一个私有数据成员balance用于存放储户在该行的存款数,另有一个友元函数Total用于计算储户在这3家银行中的总存款。类结构图如图6-1所示。

因为觉得类的私有数据成员只有balance太不正常了,因此增加了成员Id和Key,分别表示账户号码和密码。只有当三个银行的Id和Key都相同时,用户才能访问balance成员,Total函数才能成功执行。

代码如下:

 #include<iostream>
using namespace std;
#include<string>
class BBank;
class GBank; //Total同时是三个类的友元函数,必须在创建类前先声明所有类 class CBank //CBank类的声明
{public:
CBank(char*,char*,double); //构造函数原型声明
friend void Total(CBank &,BBank &,GBank &); //声明Total函数为CBank类的友元函数
private:
char id[]; //账户名
char key[]; //6位密码
double balance; //银行存款
}; CBank::CBank(char Id[],char Key[],double Balance) //构造函数的类外定义
{
for(int i=;i<;i++)
id[i]=Id[i];
for(int j=;j<;j++)
key[j]=Key[j];
balance=Balance;
} class BBank //BBank类的声明
{public:
BBank(char*,char*,double); //构造函数原型声明
friend void Total(CBank &,BBank &,GBank &); //声明Total函数为BBank类的友元函数
private:
char id[];
char key[];
double balance;
}; BBank::BBank(char Id[],char Key[],double Balance) //构造函数原型声明
{
for(int i=;i<;i++)
id[i]=Id[i];
for(int j=;j<;j++)
key[j]=Key[j];
balance=Balance;
} class GBank //GBank类的声明
{public:
GBank(char*,char*,double);
friend void Total(CBank &,BBank &,GBank &); //声明Total函数为GBank类的友元函数
private:
char id[];
char key[];
double balance;
}; GBank::GBank(char Id[],char Key[],double Balance) //构造函数原型声明
{
for(int i=;i<;i++)
id[i]=Id[i];
for(int j=;j<;j++)
key[j]=Key[j];
balance=Balance;
} void Total(CBank &c,BBank &b,GBank &g) //友元函数,c、b、g分别为CBank、BBank、GBank类对象的引用
{
int s=;
for(int i=;i<;i++)
{
if(c.id[i]==b.id[i] && c.id[i]==g.id[i] && b.id[i]==g.id[i])
{
for(int j=;j<;j++)
{
if(c.key[j]==b.key[j] && c.key[j]==g.key[j] && b.key[j]==g.key[j])
{
s=; //完全正确,结果s赋值为1
continue; //继续循环判断
}
else
{
s=; //账户号码正确 ,但密码错误,结果赋值为2
break; //跳出循环判断
}
}
}
else
{
s=; //账号信息完全不符,结果赋值为3
break; //跳出循环判断
}
} switch(s) //判断结果类型
{
case :
cout<<"总存款为:"<<endl;
cout<<c.balance<<"+"<<b.balance<<"+"<<g.balance<<"="<<c.balance+b.balance+g.balance<<"元"<<endl;
break;
case :
cout<<"账号密码错误!"<<endl;
break;
case :
cout<<"账号名称不符!"<<endl;
break;
default:
cout<<"发生未知错误,请联系银行客服!"<<endl;
break;
}
} int main()
{
CBank c("张三","",);
BBank b("张三","",);
GBank g("张三","",);
Total(c,b,g); getchar(); getchar();
return ;
}

运行结果:

编写程序时遇到的一些问题及解决思路历程:

关于循环判断的问题:一开始我的Total函数是这样写的:

 void Total(CBank &c,BBank &b,GBank &g)
{
for(int i=;i<;i++)
{
if(c.id[i]==b.id[i] && c.id[i]==g.id[i] && b.id[i]==g.id[i])
{
for(int j=;j<;j++)
{
if(c.key[j]==b.key[j] && c.key[j]==g.key[j] && b.key[j]==g.key[j])
{
cout<<"总存款为:"<<endl;
cout<<c.balance<<"+"<<b.balance<<"+"<<g.balance<<"="<<c.balance+b.balance+g.balance<<"元"<<endl;
}
else
cout<<"账号密码错误!"<<endl;
}
}
else
cout<<"账号信息不符!"<<endl;
}
}

运行结果:

和预期的不同,出现了30次结果。回到代码,发现好像也解释得通:要判断Id和Key数组中每个元素的情况,必然用到循环语句;可只要第i个元素相同,满足条件,就会执行cout输出操作。

请教了老师,他建议我自定义一个布尔函数进行判断,若循环内能满足所有判断条件,则返回true,否则返回false。我自定义了一个Verify函数,代码如下:

bool Verify(char a[],b[])
{
for(int i=;i<;i++)
{
if(c.id[i]==b.id[i] && c.id[i]==g.id[i] && b.id[i]==g.id[i])
{
for(int j=;j<;j++)
{
if(c.key[j]==b.key[j] && c.key[j]==g.key[j] && b.key[j]==g.key[j])
return true;
}
else
return false;
}
} int main()
{
CBank c("张三","",);
BBank b("张三","",);
GBank g("张三","",);
if(Verify(Id[],Key[]))
{
cout<<"总存款为:"<<endl;
cout<<c.balance<<"+"<<b.balance<<"+"<<g.balance<<"="<<c.balance+b.balance+g.balance<<"元"<<endl;
}
else cout<<"账号信息错误!"<<endl; return ;
getchar(); getchar();
}

发现又出现了新的问题:

一、  Id和Key都是类的私有成员,Verify函数无法访问它们。

二、  Verify函数是在main主函数中运行的,但该函数判断完后还有输出语句需访问类的私有成员。

三、  bool函数结果只有两种结果,无法反映多结果的情况。

问题一的解决思路:

1. 将Verify函数定义为类的友元函数。

2.将Verify的参数改成6个字符串类型,对应3个银行的Id和Key数组。

问题二的解决思路:自定义一个输出函数,它是三个类的公共友元函数。

问题三的解决思路:不使用bool型,而改用switch语句判断。

综合三个问题的思路,得出两个解决办法:

方法一:

自定义bool型判断函数和void型输出函数,他们都是三个类的友元函数,都能访问三个类的私有成员。void型输出函数根据bool型判断函数的返回值输出不同结果。

方法二:

在原Total函数中,利用bool型返回值判断的思路,定义一个变量s作为返回值。根据循环判断结果赋给s不同的值,再根据s的值输出不同的结果。开头给出的函数就是使用了法二。

总结:

两种方法都可行,两者的时间复杂度相同。但法一较法二不能做到解决问题三的优化,因此法二有更大的可拓展性和适应性。

《C++面向对象程序设计》第6章课后编程题2拓展的更多相关文章

  1. 面向对象程序设计--Java语言第二周编程题:有秒计时的数字时钟

    有秒计时的数字时钟 题目内容: 这一周的编程题是需要你在课程所给的时钟程序的基础上修改而成.但是我们并不直接给你时钟程序的代码,请根据视频自己输入时钟程序的Display和Clock类的代码,然后来做 ...

  2. c++面向对象程序设计第四章课后习题

    这是书上的习题,我使用的是VS2010运行编译的 原习题: 4.有两个矩阵a和b,均为两行三列.求两个矩阵之和.重载运算符“+”,使之能用于矩阵相加.如c=a+b. #include<iostr ...

  3. 面向对象程序设计--Java语言第一周编程题:分数

    分数 题目内容: 设计一个表示分数的类Fraction.这个类用两个int类型的变量分别表示分子和分母. 这个类的构造函数是: Fraction(int a, int b) 构造一个a/b的分数. 这 ...

  4. 已看1.熟练的使用Java语言进行面向对象程序设计,有良好的编程习惯,熟悉常用的Java API,包括集合框架、多线程(并发编程)、I/O(NIO)、Socket、JDBC、XML、反射等。[泛型]\

    1.熟练的使用Java语言进行面向对象程序设计,有良好的编程习惯,熟悉常用的Java API,包括集合框架.多线程(并发编程).I/O(NIO).Socket.JDBC.XML.反射等.[泛型]\1* ...

  5. Java面向对象程序设计第14章3-8和第15章6

    Java面向对象程序设计第14章3-8和第15章6 3.完成下面方法中的代码,要求建立一个缓冲区,将字节输入流中的内容转为字符串. import java.io.*; public class tes ...

  6. Java面向对象程序设计第9章1-9

    Java面向对象程序设计第9章1-9 1. 线程和进程的联系和区别是什么? 联系: 一个进程可以包括多个线程. 区别: 进程: 进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动,它是系统 ...

  7. Java面向对象程序设计第8章3-5

    Java面向对象程序设计第8章3-5 3.String类型有什么特点? 一旦赋值,便不能更改其指向的字符对象 如果更改,则会指向一个新的字符对象 不能为null 4.String什么时候进行值比较,什 ...

  8. Java面向对象程序设计第7章1-8

    Java面向对象程序设计第7章1-8 1."程序中凡是可能出现异常的地方必须进行捕获或拋出",这句话对吗? 不对. 异常分两类,runtime异常和非runtime异常. runt ...

  9. Java面向对象程序设计第5章1-9

    1.面向对象的主要特征是什么? 三大特征是:封装.继承和多态. 封装:是指将某事物的属性和行为包装到对象中,这个对象只对外公布需要公开的属性和行为,而这个公布也是可以有选择性的公布给其它对象. 继承: ...

随机推荐

  1. ugligy 转

    3.配置gulpfile.js 3.1.基本使用 JavaScript 1 2 3 4 5 6 7 8 var gulp = require('gulp'),     uglify = require ...

  2. vue项目实战经验汇总

    目录 1.vue框架使用注意事项和经验 1.1 解决Vue动态路由参数变化,页面数据不更新 1.2 vue组件里定时器销毁问题 1.3 vue实现按需加载组件的两种方式 1.4 组件之间,父子组件之间 ...

  3. JVM解毒——JVM与Java体系结构

    你是否也遇到过这些问题? 运行线上系统突然卡死,系统无法访问,甚至直接OOM 想解决线上JVM GC问题,但却无从下手 新项目上线,对各种JVM参数设置一脸懵逼,直接默认,然后就JJ了 每次面试都要重 ...

  4. python3 kubernetes api 使用

    一.安装 github:https://github.com/kubernetes-client/python 安装 pip install kubernetes 二.认证 1.kubeconfig文 ...

  5. centos 7 设置 本地更新源

    #yum-config-manager --disable \*--屏弊所有更新源#mkdir /r7iso# cd /run/media/{用户名}/CentOS\ 7\ x86_64/ #cp - ...

  6. iptables 实例

    开启ip段192.168.1.0/24端的80口 开启ip段211.123.16.123/24端ip段的80口 # iptables -I INPUT -p tcp --dport 80 -j DRO ...

  7. 珠峰-架构6-es6

    let aa = ; { console.log(aa); } // ----- let aa = ; { console.log(aa); // 报错 aa is not defined let a ...

  8. SharePoint PowerShell SendEmail

    前言 最近碰到这样一个需求,用户需要个简单的定时邮件提醒,就是抓取SharePoint某个列表里的值,然后作为邮件地址/邮件主题/邮件内容发送出去. 自己想了想,既然用户要求每天定时发送,那么肯定是任 ...

  9. Java虚拟机——JVM

    一.JVM整体架构 1.JVM(Java虚拟机):指以软件的方式模拟具有完整硬件系统功能.运行在一个完全隔离环境中的完整计算机系统,是物理机的软件实现.常用的虚拟机有VMWare.Virtual Bo ...

  10. 传智播客C++视频学习笔记(3)

    #include<iostream> using namespace std; //内存分区模型 //代码区,存放二进制代码,由操作系统进行管理 //全局区,存放全局变量.静态变量.常量( ...