设计一个程序,其中有3个类CBank、BBank、GBank,分别为中国银行类,工商银行类和农业银行类。每个类都包含一个私有数据成员balance用于存放储户在该行的存款数,另有一个友元函数Total用于计算储户在这3家银行中的总存款。类结构图如图6-1所示。
因为觉得类的私有数据成员只有balance太不正常了,因此增加了成员Id和Key,分别表示账户号码和密码。只有当三个银行的Id和Key都相同时,用户才能访问balance成员,Total函数才能成功执行。
代码如下:
1 #include2 using namespace std; 3 #include<string> 4 class BBank; 5 class GBank; //Total同时是三个类的友元函数,必须在创建类前先声明所有类 6 7 class CBank //CBank类的声明 8 {public: 9 CBank(char*,char*,double); //构造函数原型声明 10 friend void Total(CBank &,BBank &,GBank &); //声明Total函数为CBank类的友元函数 11 private: 12 char id[30]; //账户名 13 char key[6]; //6位密码 14 double balance; //银行存款 15 }; 16 17 CBank::CBank(char Id[30],char Key[6],double Balance) //构造函数的类外定义 18 { 19 for(int i=0;i<30;i++) 20 id[i]=Id[i]; 21 for(int j=0;j<6;j++) 22 key[j]=Key[j]; 23 balance=Balance; 24 } 25 26 class BBank //BBank类的声明 27 {public: 28 BBank(char*,char*,double); //构造函数原型声明 29 friend void Total(CBank &,BBank &,GBank &); //声明Total函数为BBank类的友元函数 30 private: 31 char id[30]; 32 char key[6]; 33 double balance; 34 }; 35 36 BBank::BBank(char Id[30],char Key[6],double Balance) //构造函数原型声明 37 { 38 for(int i=0;i<30;i++) 39 id[i]=Id[i]; 40 for(int j=0;j<6;j++) 41 key[j]=Key[j]; 42 balance=Balance; 43 } 44 45 class GBank //GBank类的声明 46 {public: 47 GBank(char*,char*,double); 48 friend void Total(CBank &,BBank &,GBank &); //声明Total函数为GBank类的友元函数 49 private: 50 char id[30]; 51 char key[6]; 52 double balance; 53 }; 54 55 GBank::GBank(char Id[30],char Key[6],double Balance) //构造函数原型声明 56 { 57 for(int i=0;i<30;i++) 58 id[i]=Id[i]; 59 for(int j=0;j<6;j++) 60 key[j]=Key[j]; 61 balance=Balance; 62 } 63 64 void Total(CBank &c,BBank &b,GBank &g) //友元函数,c、b、g分别为CBank、BBank、GBank类对象的引用 65 { 66 int s=0; 67 for(int i=0;i<30;i++) 68 { 69 if(c.id[i]==b.id[i] && c.id[i]==g.id[i] && b.id[i]==g.id[i]) 70 { 71 for(int j=0;j<6;j++) 72 { 73 if(c.key[j]==b.key[j] && c.key[j]==g.key[j] && b.key[j]==g.key[j]) 74 { 75 s=1; //完全正确,结果s赋值为1 76 continue; //继续循环判断 77 } 78 else 79 { 80 s=2; //账户号码正确 ,但密码错误,结果赋值为2 81 break; //跳出循环判断 82 } 83 } 84 } 85 else 86 { 87 s=3; //账号信息完全不符,结果赋值为3 88 break; //跳出循环判断 89 } 90 } 91 92 switch(s) //判断结果类型 93 { 94 case 1: 95 cout<<"总存款为:"<<endl; 96 cout< "+"< "+"< "="< "元"<<endl; 97 break; 98 case 2: 99 cout<<"账号密码错误!"<<endl; 100 break; 101 case 3: 102 cout<<"账号名称不符!"<<endl; 103 break; 104 default: 105 cout<<"发生未知错误,请联系银行客服!"<<endl; 106 break; 107 } 108 } 109 110 111 int main() 112 { 113 CBank c("张三","111111",2536); 114 BBank b("张三","111111",11365); 115 GBank g("张三","111111",88565); 116 Total(c,b,g); 117 118 getchar(); getchar(); 119 return 0; 120 }
运行结果:
编写程序时遇到的一些问题及解决思路历程:
关于循环判断的问题:一开始我的Total函数是这样写的:
1 void Total(CBank &c,BBank &b,GBank &g) 2 { 3 for(int i=0;i<30;i++) 4 { 5 if(c.id[i]==b.id[i] && c.id[i]==g.id[i] && b.id[i]==g.id[i]) 6 { 7 for(int j=0;j<6;j++) 8 { 9 if(c.key[j]==b.key[j] && c.key[j]==g.key[j] && b.key[j]==g.key[j]) 10 { 11 cout<<"总存款为:"<<endl; 12 cout<"+"< "+"< "="< "元"<<endl; 13 } 14 else 15 cout<<"账号密码错误!"<<endl; 16 } 17 } 18 else 19 cout<<"账号信息不符!"<<endl; 20 } 21 }
运行结果:
和预期的不同,出现了30次结果。回到代码,发现好像也解释得通:要判断Id和Key数组中每个元素的情况,必然用到循环语句;可只要第i个元素相同,满足条件,就会执行cout输出操作。
请教了老师,他建议我自定义一个布尔函数进行判断,若循环内能满足所有判断条件,则返回true,否则返回false。我自定义了一个Verify函数,代码如下:
bool Verify(char a[30],b[6]) { for(int i=0;i<30;i++) { if(c.id[i]==b.id[i] && c.id[i]==g.id[i] && b.id[i]==g.id[i]) { for(int j=0;j<6;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("张三","111111",2536); BBank b("张三","111111",11365); GBank g("张三","111111",88565); if(Verify(Id[30],Key[6])) { cout<<"总存款为:"<<endl; cout<"+"< "+"< "="< "元"<<endl; } else cout<<"账号信息错误!"<<endl; return 0; 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的值输出不同的结果。开头给出的函数就是使用了法二。
总结:
两种方法都可行,两者的时间复杂度相同。但法一较法二不能做到解决问题三的优化,因此法二有更大的可拓展性和适应性。