一、实验目的: 1.掌握对象数组、对象指针,对象的赋值和复制,要求熟练应用。 2.掌握静态成员函数和静态数据成员,友元函数,类模板,要求熟练应用。 3.了解运算符重载的概念,掌握运算符重载的方法、规则。 4.掌握运算符重载函数做为类成员函数和友元函数。 5.掌握双目、单目运算符的重载,流插入运算符和流提取运算符的重载 | |
二、实验内容 1.读程序,分析它执行后的输出结果,并上机进行测试验证。 #include <iostream.h> #include <string.h> class MyClal { char *str; public: MyClal(char *s); MyClal() { cout<<"Destructor:Destroying=>"<<str<<"\n"; delete str; } void print(){cout<<"------printed by=>"<<str<<endl;} }; MyClal::MyClal(char *s) { cout<<"Constructor:Initializing=>"<<s<<"\n"; str=new char[strlen(s)+1]; strcpy(str,s); } MyClal IO("Global IO"); void main() { IO.print(); MyClal I1("function_Local I1"); int cond=2; I1.print(); while(cond) { cout<<"In block.\n"; MyClal I2("Block_Local I2"); I2.print(); static MyClal I3("Static I3"); cond--; } cout<<"Exited block.\n"; } 2.编写程序。设计一个职工类Person,一个系有若干个职工,按职务分为系主任、室主任和职工,给出他们之间的领导关系。 实现方法: (1)类Person有姓名、职务和指向领导的指针等私有数据,以及两个构造函数和以下成员函数:setleader()(设置当前职工的领导);getname()(获得职工成员);getleader()(获取领导者对象指针);disp()(输出姓名和职务)。 (2)定义如下样式的主函数。 void main() { Person p[]={ Person("王华","室主任"),Person("李明","职工"), Person("陈强","系主任"),Person("章城","职工"), Person("张伟","室主任"),Person("许源","职工"), }; p[0].setleader(p[2]); p[1].setleader(p[0]); p[3].setleader(p[4]); p[4].setleader(p[2]); p[5].setleader(p[4]); cout<<" 姓名 职务 领导姓名\n"; cout<<"-------------------------\n"; for(int i=0;i<6;i++) { p[i].disp(); printf("%10s\n",(p[i].getleader())->getname()); } } 程序: #include<iostream> #include<stdio.h> #include<string.h> using namespace std; class Person { char name[10]; char prof[10]; Person* leader; public: Person() { strcpy_s(name, "\0"); } Person(const char n[], const char p[]) { strcpy_s(name, n); strcpy_s(prof, p); leader = new Person; } void setleader(Person& p) { leader = &p; } // 对象引用作为参数 char* getname() { return name; } Person* getleader() { return leader; } void disp() { printf("%10s %10s%", name, prof); } }; int main() { Person p[] = { Person("王华","室主任"),Person("李明","职工"), Person("陈强","系主任"),Person("章城","职工"), Person("张伟","室主任"),Person("许源","职工") }; p[0].setleader(p[2]); p[1].setleader(p[0]); p[3].setleader(p[4]); p[4].setleader(p[2]); p[5].setleader(p[4]); cout << "╔════════════════════════════════╗" << endl; cout << "║ 姓名 ║ 职务 ║ 领导姓名║" << endl; cout << "╚════════════════════════════════╝" << endl; for (int i = 0; i < 6; i++) { p[i].disp(); printf("%10s\n", (p[i].getleader())->getname()); } } 3.编写程序。定义如下形式的类模板myTmplt,其实例化后的类对象的数据成员由三元组(x,y,z)所构成,而数据的类型则为可变化的类型T(并假设T为可比较大小的某种类型)。模板中还设有其他几个成员函数,用于对三元组数据进行指定处理。 template <class T>class myTmplt{ T x,y,z; public: myTmplt(T x0,T y0,T z0){x=x0;y=y0;z=z0;} //构造函数 T max(); //求三个数据成员中的最大者 bool order(); //三个数据成员从小到大是否有序 void print(); //屏幕显示数据成员 }; 编写主函数,对所定义的类模板实例化而后进行应用,验证其正确性。 实现方法: (1)编写类模板myTmplt中各成员函数的实现代码,完成对它们的具体定义。 (2)可编写类似于如下样式的主函数,对所定义的类模板进行使用。 void main() { myTmplt<int>s1(1,2,5); s1.print(); cout<<“s1.max=”<<s1.max()<<endl; if(s1.order()) cout<<“s1.order()=>OK!”<<endl; myTmplt<char>s2(‘A’,‘t’,‘f’); …… } 程序: #include <iostream> using namespace std; #include <iostream> using namespace std; template <class T> class myTmplt { T x, y, z; public: myTmplt(T x0, T y0, T z0) { x = x0; y = y0; z = z0; } //构造函数 T max() { if (x > y) { if (x > z) { return x; } else { return z; } } else { if (y > z) { return y; } else { return z; } } } //求三个数据成员中的最大者 bool order() { if (x <= y && y <= z) { return 1; } else { return 0; } } //三个数据成员从小到大是否有序 void print() { cout << x << " " << y << " " << z << endl; } //屏幕显示数据成员 }; void main() { myTmplt<int>s1(1, 2, 5); s1.print(); cout << "s1.max = " << s1.max() << endl; if (s1.order()) cout << "s1.order() = > OK!" << endl; myTmplt<char>s2('A', 't', 'f'); s2.print(); cout << "s2.max = " << s2.max() << endl; if (s2.order()) cout << "s2.order() = > OK!" << endl; else cout << "s2.order() = > WRONG!" << endl; system("pause"); } 4.编写程序。有一个学生类student,包括学生姓名、成绩,设计一个友元函数,输出成绩对应的等级:≥90,优;80~89,中;70~79,中;60~69,及格;<60,不及格。 实现方法: (1)将学生类student的trans()函数设计成友元函数。 (2)可在学生类student中定义私有数据name、deg、level,定义带参构造函数、成员函数getname()、disp(),定义友元函数trans()(student &s)。 (3)编写主函数,实现本题功能,函数原型样式可按如下定义。 void main() { student st[]={ student("王华",78),student("李明",92), student("张伟",62),student("孙强",88)}; cout<<"输出结果:"<<endl; cout<<setw(10)<<"姓名"<<setw(6)<<"成绩"<<setw(8)<<"等级"<<endl; for(int i=1;i<4;i++) { trans(st[i]); st[i].disp(); } } 程序: #include<iostream> using namespace std; #include<string> class student { friend void trans(student& s); private: string name; int deg; public: student() {} student(string name, int deg) { this->name = name; this->deg = deg; } string level; void disp()//≥90,优;80~89,中;70~79,中;60~69,及格;<60,不及格。 { if (deg < 60) { this->level = "不及格"; } if (60 <= deg <= 69) { this->level = "及格"; } if (70 <= deg <= 89) { this->level = "中"; } if (deg >= 90) { this->level = "优秀"; } cout << level << endl; } }; void trans(student& s) { cout << " " << s.name << " " << s.deg << " "; } string setw(int n) { string w; for (int i = 0; i < n; i++) { w += " "; } return w; } int main() { student st[] = { student("王华",78),student("李明",92), student("张伟",62),student("孙强",88) }; cout << "输出结果:" << endl; cout << setw(10) << "姓名" << setw(6) << "成绩" << setw(8) << "等级" << endl; for (int i = 1; i < 4; i++) { trans(st[i]); st[i].disp(); } } 5.编写程序。定义一个复数类Complex,重载运算符“+”、“-”、“*”、“/”,使之能用于复数的加减乘除运算。编写程序,分别求两个复数的和、差、积和商。 实现方法: (1)要求重载运算符“+”、“-”的函数为成员函数,重载运算符“*”、“/”的函数为友元函数。 (2)方法如第1题的(1)—(5)。 程序: 程序: #include <iostream> using namespace std; class Complex { public: friend Complex operator+(Complex c1, Complex c2); friend Complex operator-(Complex c1, Complex c2); friend Complex operator*(Complex c1, Complex c2); friend Complex operator/(Complex c1, Complex c2); Complex(float r, float i) { imag = i; real = r; } void disp() { cout << real; if (imag > 0) { cout << "+"; } if (imag != 0) { cout << imag << "i"; } cout << endl; } private: float real, imag; }; Complex operator+(Complex c1, Complex c2) { Complex temp(0, 0); temp.real = c1.real + c2.real; temp.imag = c1.imag + c2.imag; return temp; } Complex operator-(Complex c1, Complex c2) { Complex temp(0, 0); temp.real = c1.real - c2.real; temp.imag = c1.imag - c2.imag; return temp; } Complex operator*(Complex c1, Complex c2) { Complex temp(0, 0); temp.real = c1.real * c2.real - c1.imag * c2.imag; temp.imag = c1.real * c2.imag + c1.imag * c2.real; return temp; } Complex operator/(Complex c1, Complex c2) { Complex temp(0, 0); temp.real = (c1.real * c2.real + c1.imag * c2.imag) / (c2.imag * c2.imag + c2.real * c2.real); temp.imag = (c1.imag * c2.real - c1.real * c2.imag) / (c2.imag * c2.imag + c2.real * c2.real); return temp; } int main() { float a, b, c, d; cout << "输入两个数字的实部和虚部" << endl; cin >> a >> b >> c >> d; Complex c1(a, b), c2(c, d), c3(0, 0); cout << "这两个数字分别是" << endl; c1.disp(); c2.disp(); cout << "他们的和是:"; (c1 + c2).disp(); cout << "他们的差是:"; c3 = c1 - c2; c3.disp(); cout << "他们的乘积是:"; (c1 * c2).disp(); cout << "他们相除是:"; (c1 / c2).disp(); system("pause"); return 0; } 6.编写程序。定义一个二维方阵类matrix。通过重载二元运算符“+”、“-”、“*”和一元运算符“~”,来实现矩阵加、矩阵减、矩阵乘以及矩阵转置。 实现方法: (1)首先假定矩阵行、列数r和c为固定常数,且被处理的矩阵数据存放于matrix类的私有数据成员mem数组之中,并以类成员方式重载各运算符。可按照如下样式自定义该matrix类。 const int r=3; const int c=3; class matrix { int mem[r][c]; //矩阵r行c列的数据存放于mem数组中 public: }; (2)编写类似于如下形式的主函数,对matrix类对象及各种重载运算符进行使用,以验证它们的正确性。 void main() { int a[3][3]={}1,2,3,4,5,6,7,8,9}; int b[3][3]={}1,2,3,0,1,2,-1,0,1}; matrix x(a),y(b); cout<<“----------x=-------------”<<endl; x.display(); cout<<“----------y=-------------”<<endl; y.display(); cout<<“----------x+y=-------------”<<endl; (x+y).display(); cout<<“----------x-y=-------------”<<endl; (x-y).display(); cout<<“----------x*y=-------------”<<endl; (x*y).display(); cout<<“----------~x=-------------”<<endl; (~x).display(); } 程序: #include <iostream> using namespace std; const int r = 3; const int c = 3; const int k = 3; class matrix { int a[r][c]; public: matrix() {} matrix(int t[r][c]) { for (int i = 0; i < r; i++) for (int j = 0; j < c; j++) a[i][j] = t[i][j]; } friend matrix operator+ (matrix& a, matrix& b); //矩阵加 friend matrix operator- (matrix& a, matrix& b); //矩阵减 friend matrix operator* (matrix& a, matrix& b); //矩阵乘 friend matrix operator~ (matrix& a); //矩阵转置 void display(); }; //注意分号 matrix operator +(matrix& a, matrix& b) //分号去掉 { matrix ret; for (int i = 0; i < r; i++) for (int j = 0; j < c; j++) ret.a[i][j] = a.a[i][j] + b.a[i][j]; return ret; } matrix operator -(matrix& a, matrix& b) { matrix ret; for (int i = 0; i < r; i++) for (int j = 0; j < c; j++) ret.a[i][j] = a.a[i][j] - b.a[i][j]; return ret; } matrix operator* (matrix& a, matrix& b) { matrix ret; for (int i = 0; i < r; i++) for (int j = 0; j < c; j++) { ret.a[i][j] = 0; for (int l = 0; l < k; l++) ret.a[i][j] = a.a[i][j] + b.a[i][j]; } return ret; } matrix operator~ (matrix& a) { matrix ret; for (int i = 0; i < r; i++) for (int j = 0; j < c; j++) ret.a[j][i] = ~a.a[i][j]; return ret; } void matrix::display() { for (int i = 0; i < r; i++) { for (int j = 0; j < c; j++) cout << this->a[i][j] << " "; cout << endl; } } int main() { int a[3][3] = { 1,2,3,4,5,6,7,8,9 }; int b[3][3] = { 1,2,3, 0,1,2, -1,0,1 }; matrix x(a); matrix y(b); cout << "-------- x= ------------" << endl; x.display(); //按设定格式显示出第一个矩阵 cout << "-------- y= ------------" << endl; y.display(); //按设定格式显示出第二个矩阵 cout << "-------- x+y= ------------" << endl; (x + y).display(); //输出结果矩阵 x+y cout << "--------- x-y= ---------" << endl; (x - y).display(); //输出结果矩阵x-y cout << "--------- x*y= ---------" << endl; (x * y).display(); //输出结果矩阵x*y cout << "--------- ~x= ---------" << endl; (~x).display(); //输出结果矩阵~x system("PAUSE"); } 7.编写程序。定义一个字符串类String,用来存放不定长的字符串,重载运算符“==”、“<”和“>”,用于两个字符串的等于、小于和大于的比较运算。 实现方法: (1)可定义如下样式的类String。 class String { public: String( ){ p=NULL; } //默认构造函数 String(char *str); //构造函数 void display( ); private: char *p; //字符型指针,用于指向字符串 };
程序: #include<iostream> #include<cstring> using namespace std; class String { public: String()//默认构造函数 { p = NULL; } String(const char* str);//构造函数 void display(); friend bool operator>(String& string1, String& string2); friend bool operator<(String& string1, String& string2); friend bool operator==(String& string1, String& string2); private: const char* p; }; String::String(const char* str) { p = str;} void String::display() { cout << p; } bool operator>(String& string1, String& string2) { if (strcmp(string1.p, string2.p) > 0) return true; else return false; } bool operator<(String& string1, String& string2) { if (strcmp(string1.p, string2.p) < 0) return true; else return false; } bool operator==(String& string1, String& string2) { if (strcmp(string1.p, string2.p) == 0) return true; else return false; } void compare(String& string1, String& string2) { if (operator>(string1, string2) == 1) { string1.display(); cout << ">"; string2.display(); cout << endl; } else if (operator<(string1, string2) == 1) { string1.display(); cout << "<"; string2.display(); cout << endl; } else if (operator==(string1, string2) == 1) { string1.display(); cout << "=="; string2.display(); cout << endl; } } int main() { String string1("discourage"), string2("analyse"), string3("numerous"), string4("discourage");//定义对象 compare(string1, string2); compare(string2, string3); compare(string1, string4); return 0; } 分析与讨论: 1.对象的赋值和复制有什么区别? 答:对象的赋值是对一个已经存在的对象赋值,因此必须先定义被赋值的对象,才能进行对象的赋值。而对象的复制则是从无到有地建立一个新对象,并使它与一个已有的对象的完全相同 (包括对象的结构和成员的值)。 2.复制构造函数的作用是什么? 答:使用一个已经存在的对象(此对象由复制构造函数的参数决定),去初始化同类的一个新对象。 3.如果A类是B类的友元,B类是C类的友元,那么A类是C类的友元吗? 答:友元的关系是不能传递的,所以类A不是类C的友元 4.使用静态数据成员有什么特点和优势? 答: 特点:不管这个类创建多少个对象,其静态成员在内存中只保留一份副本,这个副本为该类的所有对象所共享。面对对象方法中还有类属性的概念,类属性是描述类的所有对象的共同特征的一个数据项,对于任何对象实例,它的属性值是相同的,C++通过静态数据成员来实现类属性。 优势:静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其它全局名字冲突的可能性;可以实现信息隐藏。 5.双目运算符如何对类的对象进行运算? 答:运算对象的个数是2的运算符称为双目运算符 6.哪些运算符是不允许重载的? (1).(成员访问运算符) (2)*(成员指针访问运算符) (3)::(域运算符) (4)sizeof(长度运算符) (5)?:(条件运算符) 7.为什么算术运算符“+”“-”“*”“/”应该重载为友元函数? 答:多元运算符重载为成员函数的时候,是调用的第一个运算数的成员函数 |
《C++程序设计》实验报告(三)之 类的基本操作和运算符重载的设计与实现
于 2024-01-29 17:58:15 首次发布