实验6-静态成员和友元
- 格式:doc
- 大小:282.00 KB
- 文档页数:19
实验4 含有类的静态成员与类的友元的C++程序设计专业:计算机科学与技术班级:10计本1班学号:姓名:实验地点:B102实验时间:2011/11/1 指导教师:李佐勇一、实验目的1.理解类的静态成员解决共享问题的机制;2.掌握类的静态数据成员与静态函数成员的实现方法;3.理解利用友元关系实现数据共享的机制,掌握类的友元函数以及友元类的实现方法;4.学习多文件结构在C++程序中的使用。
二、实验环境一台PC机,Windows XP操作系统,Visual C++ 6.0开发环境。
三、实验内容1.设计一个解决王婆卖瓜问题的程序。
王婆卖瓜,每卖一个瓜,需记录该瓜的重量,还要记录所卖出的总重量和总个数,同时还允许退瓜。
设计一个具有静态数据、函数成员的watermelon类。
实现提示:西瓜类有3个数据成员:重量weight、总重量total_weight以及总个数total_number。
因为不论西瓜是否卖出,总重量total_weight和总个数total_number这两个数据总是要保留的,且这两个数据与单个的西瓜无关联,因此这两个数据要申明为静态数据成员。
成员函数:卖瓜用构造函数模拟,退瓜用析构函数模拟,瓜重用disp成员函数给出屏幕提示。
为了用不与特定对象相联系的静态成员函数来访问静态数据,还需要定义一个显示总重量和总个数的静态成员函数total_disp。
2.设计一个程序,其中有3个类,即CBank、BBank和GBank,分别为中国银行类、工商银行类和农业银行类。
每个类都包含一个私有数据balance,用于存放储户在该行的存款数,另有一个友元函数total用于计算储户在这3家银行中的总存款数。
3. 设计一个程序,其中有2个类,Point类为点类,包含2个私有数据x和y,表示点的坐标,line类为直线类,包含3个私有数据a、b和c,表示直线方程ax+by+c=0。
另有一个友元函数dist,用于计算一个点到直线的距离。
实验一类和对象一、实验目的:掌握类的设计和对象的创建及相关知识点如对象数组、类聚合、友元函数、静态成员。
二、实验内容:1、设计圆类,求两个圆的位置关系;2、设计圆类和直线类,求直线与圆的位置关系;3、设计学生类,求某班学生成绩的最高分、最低分及平均分;4、设计部门类和教师类,其中部门类成员为教师类的子对象;5、设计家庭银行账户类,其中账户资金为静态数据成员,为家庭成员共享;6、设计复数类,友元函数实现复数的加减。
三、实验过程:1、根据实验题目确定需要设计哪些类、各类中包含哪些数据成员和函数成员,设计各成员的访问权限,设计数据成员的数据类型,设计函数成员的函数原型;2、给出类设计的程序实现,特别要注意重载构造函数的实现;3、在主函数中完成题目中的逻辑,一般情况下需要创建相关类的对象,通过对象对成员函数的调用或者通过对象指针对成员函数的调用完成相应的功能。
四、参考程序代码:1、设计圆类,求两个圆的位置关系#include <iostream>#include <math.h>using namespace std;class Circle{private:float a,b,r;public:Circle(float c,float d,float e){a=c;b=d; r=e;}friend void position(Circle &,Circle &);};void position(Circle &c1,Circle &c2){float n,m,p;p=sqrt((c1.a-c2.a)*(c1.a-c2.a)+(c1.b-c2.b)*(c1.b-c2.b)); n=fabs(c1.r-c2.r);m=c1.r+c2.r;if(p>m)cout << "相离";if(p==m)cout << "相切";if(p<m)cout << "相交";}int main(){float a,b,c,d,e,f;cin >> a >> b >> c >> d >> e >> f ;Circle c1(a,b,c),c2(d,e,f);position(c1,c2);return 0;}运行结果:2、设计圆类和直线类,求直线与圆的位置关系#include<iostream>#include<math.h>using namespace std;class Circle//圆类{private:float x,y,r;public:Circle(float a,float b,float c) {x=a;y=b;r=c;}float getx(){return x;}float gety(){return y;}float getr(){return r;}};class Line//直线类{private:float a,b,c;public:Line(float x,float y,float z){a=x;b=y;c=z;}void position(Circle c1){float d=fabs(a*c1.getx()+b*c1.gety()+c)/sqrt(a*a+b*b) ;//圆心到直线的距离if(d<c1.getr())cout << "相交";if((d-c1.getr())<0.000001)cout << "相切";cout << "相离";}};int main(){Line l1(3,3,4);//创建直线对象Circle c1(-23,3,7);//创建圆对象l1.position(c1);return 0;}运行结果:3、设计学生类,求某班学生成绩的最高分、最低分及平均分#include <iostream>#include <string.h>using namespace std;class Student{private:char name[20],xuehao[20];float math;public:Student(){}Student(char *na,char *xu,float ma):math(ma) {strcpy(name,na);strcpy(xuehao,xu);}void set(char *na,char *xu,float ma){math=ma;strcpy(name,na);strcpy(xuehao,xu);}char *get_name(){return name;}char *get_xuehao(){return xuehao;float get_math(){return math;}};void max_min(Student stu[],int n){Student max,min;max=min=stu[0];for(int i;i<n;i++){if(stu[i].get_math()>max.get_math())max=stu[i];if(stu[i].get_math()<min.get_math())min=stu[i];}cout << "学生成绩最高:" << max.get_name() << "," << max.get_xuehao() << "," << max.get_math() << endl;cout << "学生成绩最低:" << min.get_name() << "," << min.get_xuehao() << "," << min.get_math() << endl;}void ave(Student stu[],int n){float sum=0;for(int i=0;i<n;i++){sum=sum+stu[i].get_math();cout << "ave=" << sum/n;}int main(){char na[20],xu[20];float ma;Student stu[20];int n;cout << "请输入学生总人数"; cin >> n;for(int i=0;i<n;i++){cin >> na >> xu >> ma ; stu[i].set(na,xu,ma); }max_min(stu,n);ave(stu,n);return 0;}运行结果:4、设计部门类和教师类,其中部门类成员为教师类的子对象#include <iostream>#include <string.h>using namespace std;class Department{private:int dep_num;char dep_master[20];char dep_name[20];public:Department(){}Department(int num,char *ma,char *na){dep_num=num;strcpy(dep_master,ma);strcpy(dep_name,na);}void show(){cout << dep_num << "," << dep_master << "," << dep_name ; }};class Teacher{private:char name[20];char haoma[20];Department dep;public:Teacher(char *n,char *nu,int num,char *ma,char *na):dep(num,ma,na) {strcpy(name,n);strcpy(haoma,nu);}void show(){dep.show();cout << "," << name << "," << haoma << endl;}};int main(){Teacher hp("wanghai","12345",6,"kiki","computer");hp.show();return 0;}运行结果:5、设计家庭银行账户类,其中账户为静态数据成员,为家庭成员共享#include <iostream>#include <string.h>using namespace std;class Familymember//家庭成员类{private:char membername[10];//成员名public:static float account;//共享账户资金 Familymember(char *name);static void save(float money);//存钱 static void pay(float money);//支出 static void show(); //显示账户余额};float Familymember::account=0;Familymember::Familymember(char *name) {strcpy(membername,name);}void Familymember:: save(float money) {account= account+money;}void Familymember:: pay(float money){account= account-money;}void Familymember:: show(){cout<<account<<endl;}int main()//主函数{ Familymember husband("wang"),wife("Li"); husband.save(10000);wife.pay(3000);wife.save(5000);wife.show();husband. show();}运行结果:6、设计复数类,友元函数实现复数的加减#include <iostream>using namespace std;class Fushu{private:float ss,xs;public:Fushu(){}Fushu(float a,float b){ss=a;xs=b;}friend Fushu jiafa(Fushu &f1,Fushu &f2){return Fushu((f1.ss+f2.ss),(f1.xs+f2.xs)); }friend Fushu jian(Fushu &f1,Fushu &f2){return Fushu((f1.ss-f2.ss),(f1.xs-f2.xs)); }void show(){cout << ss << " + " << xs << "i" << endl; }};int main(){Fushu f1(2,3),f2(4,5);Fushu f3,f4;f3=jiafa(f1,f2);f4=jian(f1,f2);f3.show();f4.show();return 0;}运行结果:。
静态成员函数静态成员函数是指在类中声明的用static关键字修饰的函数,也叫作类函数。
一般来说,它不需要访问类的数据成员,它只可以调用类的静态成员函数和友元函数,不可以调用普通成员函数,但它可以调用其他所有的成员函数。
静态成员函数也可以用于构造函数那里,因为只有静态成员函数没有隐式的this指针,所以,静态成员函数无法访问非静态成员数据。
二、静态成员函数的作用1、它可以实现自定义的初始化及赋值,所有的对象在创建时都使用相同的初始化及赋值,这样可以节省很多时间。
2、用它可以实现全局函数的功能,但与全局函数不同的是,它可以访问类的private部分。
3、它可以提供对象的总数,通过静态友元函数来实现,可以检测构造函数和析构函数的调用次数,从而检测对象的数量。
4、它可以返回类的静态成员变量,也可以用于类的计算,这种方法可以使我们不必使用全局变量。
三、静态成员函数的特点1、只有在类中才能使用静态成员函数,而不能直接在主程序中使用它们。
2、它可以调用类中所有的静态成员函数,但不能调用普通成员函数。
3、它不能操作类的非静态成员数据,但可以调用其他所有的成员函数。
4、它只能被类的静态成员函数和友元函数调用。
四、实例下面我们来看一个使用静态成员函数的实例,这个实例演示了如何使用静态成员函数来访问类的静态成员变量。
#include <iostream>using namespace std;class StaticClass{private:static int count;public://静态成员函数static int getCount(){return count;}//普通成员函数void setCount(int val){count = val;}};//静态变量初始化int StaticClass::count = 0;int main(){//设置count的值StaticClass::setCount(5);//获取count的值cout<<count的值为:<<StaticClass::getCount()<<endl;return 0;}上面的程序中,定义了一个静态变量count,在类外面定义了这个静态变量,指定了它的初值为0,在类中定义了一个静态成员函数getCount(),用于访问静态变量count,这里不用构造函数,也没有实例化任何对象,只要使用类名来调用静态成员函数就可以使用私有成员count,并且可以通过它获取静态变量count的值,并将这个值输出在屏幕上。
实验题目(共2题, 第1题) 标题:1.单词统计时限:1000 ms内存限制:10000 K总时限:3000 ms描述:使用string类和STL相关容器统计输入文本中所有单词出现的次数。
要求:(1)单词统计不分大小写,如Cambridge和CAMBRIDGE是同一单词;(2)标点符号“,.;!?”需要过滤;(3)输出结果按照字母大小从小到大排列且输出单词必须是小写,如Cambridge应转化为cambridge后输出。
输入:键盘输入文本信息,“exit”为文本结束标志。
输出:文本中出现的所有单词和频率(次数)。
注意单词和频率之间用空格隔开,最后一个输出字符串后面还有一个空格。
输入样例:SAYING GOODBYE TO CAMBRIDGE AGAINVery quietly I leftAs quietly as I came here;Quietly I wave goodbyeTo the rosy clouds in the western sky. The golden willows by the riversideAre young brides in the setting sun; Their reflections on the shimmering waves Always linger in the depth of my heart. The floatingheart growing in the sludge Sways leisurely under the water;In the gentle waves of CambridgeI would be a water plant!exit输出样例:a 1 again 1 always 1 are 1 as 2 be 1 brides 1 by 1 cambridge 2 came 1 clouds 1 depth 1 floatingheart 1 gentle 1 golden 1 goodbye 2 growing 1 heart 1 here 1 i 4 in 5 left 1 leisurely 1 linger 1 my 1 of 2 on 1 plant 1 quietly 3 reflections 1 riverside 1 rosy 1 saying 1 setting 1 shimmering 1 sky 1 sludge 1 sun 1 sways 1 the 11 their 1 to 2 under 1 very 1 water 2 wave 1 waves 2 western 1 willows 1 would 1 young 1提示:使用STL中的map,字符查找函数find和字符小写转换函数tolower。
题目1:定义一个复数类,通过重载运算符:*,/,直接实现二个复数之间的乘除运算。
编写一个完整的程序,测试重载运算符的正确性。
要求乘法“*”用友元函数实现重载,除法“/”用成员函数实现重载。
源程序1/*******************第1题*******************//******************单森汉*****************//******************2012-5-1*****************/#include<iostream>using std::cout;using std::endl;class Complex{float Real, Image;public:Complex(float r=0,float i=0) { Real=r;Image=i;}void Show(){cout <<"Real="<<Real<<'\t'<<"Image="<<Image<<'\n';}friend Complex operator *(Complex &, Complex &);Complex operator /(Complex &); //重载运算符+Complex operator +( Complex &);friend Complex operator -(Complex &, Complex &);};Complex operator *( Complex &c1,Complex &c2){Complex t;t.Real=c1.Real * c2.Real - c1.Image * c2.Image;t.Image = c1.Image*c2.Real +c1.Real* c2.Image;return t;}Complex Complex::operator /(Complex &c){Complex t;t.Real =(Real *c.Real+ Image * c.Image)/(c.Real*c.Real+ c.Image * c.Image);t.Image = (Image *c.Real - Real * c.Image)/(c.Real*c.Real+ c.Image * c.Image);return t;}Complex Complex::operator + ( Complex &c){Complex t;t.Real = Real + c.Real;t.Image = Image + c.Image;return t;}Complex operator -(Complex &c1, Complex &c2){Complex t;t.Real=c1.Real-c2.Real;t.Image=c1.Image-c2.Image;return t;}void main(){Complex c1(1,2),c2(3,4),c3;c3=c1*c2;cout<<"两个复数的乘法c3=c1*c2:";c3.Show();c3=c1/c2;cout<<"两个复数的除法c3=c1/c2:";c3.Show();Complex c4(1,2),c5(3,4),c6,c7(1,2),c8(3,0),c9; c6=c4+c5;cout<<"两个复数的加法c6=c4+c5:";c6.Show();c6=c4-c5;cout<<"两个复数的减法c6=c4-c5:";c6.Show();c9=c7+c8;cout<<"一个复数与一个实数的加法c9=c7+c8:"; c9.Show();c9=c7-c8;cout<<"一个复数与一个实数的减法c9=c7-c8:"; c9.Show();}运行结果截图题目2:定义一个向量(一维数组)类,通过重载运算符实现向量之间的加法和减法。
天津理工大学计算机科学与技术学院实验报告至学年第学期课程名称C++程序设计应用学号学生姓名年级13级专业教学班号实验地点7-219 实验时间年月日第节至第节主讲教师辅导教师实验(二)实验名称复杂形式的对象软件环境Visual C++ 6.0硬件环境台式计算机实验目的(1)掌握对象数组、对象指针的使用方法;(2)掌握对象数组、对象指针和对象引用作为函数参数的使用方法;(3)掌握类对象作为成员的使用方法;(4)掌握友元的概念和使用方法;(5)掌握静态数据成员和静态成员函数的使用方法;(6)进一步了解C++面向对象程序设计的基本思想、基本方法和基本步骤;实验内容(应包括实验题目、实验要求、实验任务等)1.代码及注释;#include<iostream>using namespace std;class Time //声明Time类{public:Time(int a=0,int b=0,int c=0) // 带默认参数的构造函数{hour=a;minute=b;second=c;}// set functionsvoid setTime(int h,int m,int s) // 设置hour, minute, second{hour=h;minute=m;second=s;}void setHour(int a) // 设置hour (确保数据在合理范围){if(a<24&&a>=0)hour=a;实验过程与实验结果(可包括实验实施的步骤、算法描述、流程、结论等)}void setMinute(int b) // 设置minute (确保数据在合理范围){if(b<60&&b>=0)minute=b;}void setSecond(int c) // 设置second (确保数据在合理范围){if(c<60&&c>=0)second=c;}int getHour() // 返回hour{return hour;}int getMinute() // 返回minute{return minute;}int getSecond() // 返回second{return second;}void printUniversal() // 按24小时格式输出时间:23:56:12{cout<<"24小时格式的时间为:"<<getHour()<<":"<<getMinute()<<":"<<getSecond()<<endl;}void printStandard() // 按12小时格式输出时间:11:56:12 (PM) 或9:23:55(AM) {if(hour>12)cout<<"12小时格式的时间为:"<<getHour()-12<<":"<<getMinute()<<":"<<getSecond()<<"(pm)"<<endl;elsecout<<"12小时格式的时间为:"<<getHour()<<":"<<getMinute()<<":"<<getSecond()<<"(am)"<<endl;}private:int hour; // 0 - 23 (24小时格式)int minute; // 0 - 59int second; // 0 - 59}; // Timel类定义结束int main(){int h1,m1,s1;int h2,m2,s2;int a;Time t1,t2;cout<<"请输入一个24小时格式的时间:"<<endl;cin>>h1>>m1>>s1;t1.setTime(h1,m1,s1);t1.printStandard();cout<<"请输入一个12小时格式的时间:(上午在最后用1表示,下午用2表示)"<<endl;cin>>h2>>m2>>s2>>a;t2.setMinute(m2);t2.setSecond(s2);if(a==1)t2.setHour(h2);elset2.setHour(h2+12);t2.printUniversal();return 0;}结果截图2.代码及注释#include<iostream>#include<cmath>using namespace std;class Location //声明类Location{public:Location(double a,double b) //构造函数{x=a;y=b;}double Getx() //成员函数,取x坐标的值{return x;}double Gety() //成员函数,取y坐标的值{return y;}double distance1(Location&a)//成员函数,求两坐标点之间的距离{double x1,y1;x1=a.Getx();y1=a.Gety();return sqrt((x1-x)*(x1-x)+(y1-y)*(y1-y));}friend double distance2(Location&, Location&);//友元函数,求两坐标点之间的距离private:double x,y;};double distance2(Location&a, Location&b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}int main(){Location A(-3.4,-6.8);Location B(-5.5,8);double d1,d2;cout<<"A("<<A.Getx()<<","<<A.Gety()<<")"<<endl;cout<<"B("<<B.Getx()<<","<<B.Gety()<<")"<<endl;cout<<"用成员函数计算"<<endl;d1=A.distance1(B);cout<<"Distance1="<<d1<<endl;cout<<"用友员函数计算"<<endl;d2=distance2(A,B);cout<<"Distance2="<<d2<<endl;return 0;}3. #include<iostream>#include<string>using namespace std;int main(){string s[20];int y=1,n=0,i=0;while(y){cout<<"请输入一个字符串(最多"<<20-n<<"个)"<<endl;cin>>s[i];cout<<"继续输入请输入1,否则输入0"<<endl;cin>>y;n++;i++;}for (;n>=0;n--)cout<<s[n]<<" ";4.设计一个模仿类magic来实现5*5的魔方阵。
实验四输入输出流实验课程名:面向对象程序设计(C++)专业班级:学号:姓名:实验时间:实验地点:指导教师:代码分析:1)在输入时调用getline()以换行符作为输入姓名时的结束标志,已达到输入空格的目的2)输出时采用resetiosflags(ios::right)实现结束向左对齐,用setw(8)实现输出域宽为8,使用一系列的格式控制字符来实现输出格式的控制。
2. 重载运算符“<<”和“>>”,使其能够输入一件商品的信息和输出这件商品的信息。
商品的信息由编号、商品名和价格。
假如商品类Merchandise的框架如下:class merchandise{public:Merchandiss();~Merchandiss();friend istream& operator>>(istream& in,Merchandiss& s);friend ostream&operator<<(ostream& out,Merchandiss& s);private:int no;char *name;double price;};要求实现该类,并编写以下的main函数对该类进行操作。
int main(){ Merchandise mer;cin>>mer;cout<<mer;return 0;}实验代码:#include<iostream>using namespace std;class merchandise{out<<s.no<<' '<<<<' '<<s.price<<endl;return out;}int main(){merchandise mer;cin>>mer;cout<<mer;return 0;}实验结果:实验分析:先定义一个商品的类,构造函数定义为无参函数在函数体中将name置为空,其他为0.在重载>>时使用getline函数,输入name以’\n’作为结束标记重载<<时直接输出。
实验三静态成员和友元函数实验名称:静态成员和友元函数学时安排:2实验类别:设计性实验实验要求:1人1组一、实验目的和任务1)熟练掌握友元函数设计的方法2)掌握友元函数的含义,友元函数和成员函数的区别。
二、实验原理介绍根据要求正确定义静态成员和友元函数。
将别的模块声明为友元,使类中本隐藏的信息如私有和保护成员就可以被友元访问。
三、实验设备介绍软件需求: Visual C++ 6.0硬件需求: 对于硬件方面的要求,建议配置是Pentium III 450以上的CPU处理器,64MB 以上的内存,200MB的自由硬盘空间、CD-ROM驱动器、能支持24位真彩色的显示卡、彩色显示器、打印机。
四、实验内容和步骤【实验3-1】静态成员为账户类ACCOUNT增加静态成员count和 InterestRate表示账户数量和利率,增加静态成员函数GetCount返回账户数目 GetInterestRate返回银行利率class ACCOUNT {public:ACCOUNT(string accno,string name,float balance);~ACCOUNT();void Deposit(float amount);void Withdraw(float amount);float GetBalance();void Show(void);static int GetCount();static float GetInterestRate();private:static int count;static float InterestRate;string _accno,_accname;float _balance;};【实验3-2】友元函数为账户类ACCOUNT增加一个友元函数,实现账户结息,要求输出结息后的余额(不计算利息税),并在main函数中调用进行测试。
friend void Update(ACCOUNT& a);【实验3-3】(加分题)在main函数中,设计一个ACCOUNT类型的数组,为数组中的10个对象初始化,并调用成员函数测试存款、取款、显示等函数,再调用友元函数测试进行结息。
内蒙古科技大学信息工程学院计算机系《面向对象程序设计》实验报告
实验内容(由学生填写)四、实验过程
练习1 题目提供源代码如下
编译结果如下
分析之后得出结论
首先静态成员函数SetAge中不可以使用指针,也不可以直接使用非静态数据成员age 此处应该使用对象名或者类名间接引用age 其次nTotalObj为私有属性,不可以直接访问,且题目要求不可以修改其属性,则添加一个成员函数,使其返回值等于nTotalObj,则代替了原先nTotalObj的功能
修改之后的代码如下
然后再次编译运行结果如下
运行结果正确,且不影响nTotalObj的计数器功能,代码修改正确练习2
题目提供源代码如下
编译之后结果如下
分析错误原因有两点
错误1 CTeacher类中的成员函数SetStuAge不能直接访问CStudent类内嵌成员stu的数据成员age 错误2 CTeacher类构造函数的初始化含有错误,内嵌对象stu的数据成员也应该包含在内
修改之后代码如下
运行结果如下
成功运行,修改正确
练习3
根据题意,所编写代码如下
说明:
1、每个实验项目填写一份实验报告,电子版命名方式为:学号姓名项目号.doc。
例如:1167111182张三3.doc表示张三做的第3个项目的实验报告。
2、实验报告电子版应该在实验后一周内提交到教务处网站的网络综合平台对应课程下。
3、任课教师要求在收到实验报告的一周内进行批阅,并给出成绩及评语。
4、实验报告电子版由教务处网站服务器保存。
5、表格宽度可以根据实际情况伸缩。