资源描述
《面向对象程序设计》实验三
实验报告
班级 电科2班 学号 Xb11640218 姓名 张俊为
1 实验目的
(1) 了解面向对象程序设计中继承性、多态性的概念;
(2) 掌握单继承、多重继承中基类成员访问属性的变化规律及访问方法;
(3) 掌握类族中构造函数和析构函数的定义方法及调用顺序;
(4) 掌握虚函数的定义和使用方法;
2 实验任务及结果分析(代码和分析结果)
任务一:分别采用公有继承、私有继承、保护继承完成类的设计。
#include "iostream"
#include<string>
using namespace std;
class student
{public:
void get_value()
{cin>>num>>name>>sex;}
void display()
{cout<<"num: "<<num<<endl;
cout<<"name: "<<name<<endl;
cout<<"sex: "<<sex<<endl;}
private :
int num;
string name;
char sex;
};
class student1:public student
{public:
void get_value_1();
void display_1();
private:
int age;
char addr[30];
};
void student1::get_value_1()
{cin>>age>>addr;}
void student1::display_1()
{cout<<"age:"<<age<<endl;
cout<<"address:"<<addr<<endl;
}
int main()
{student stud;
student1 stud1;
stud.get_value();
stud1.get_value_1();
stud.display();
stud1.display_1();
return 0;
}
任务二:对有继承关系的程序结构进行分析。
class A
{public:
void f1( );
int i;
protected:
void f2();
int j;
private:
int k;
};
class B: public A
{public:
void f3( );
protected:
int m;
private:
int n;
};
class C: public B
{public:
void f4();
private:
int p;
};
int main()
{A a1;
B b1;
C c1;
return 0;
}
问题:
(1)在main函数中能否用通过派生类B的对象b1来引用从基类A继承来的成员i,j,k?
答:因为B是A的派生类,i是A的公有成员,j是A的保护成员,k是A的私有成员,所以在类外中,i可以,j,k不可以
(2)派生类B中的成员函数能否调用基类A中的成员函数f1、f2?
答:因为B是A的派生类,f1是A的公有成员函数,f2是A的保护成员函数,所以f1,f2都可以访问
(3)派生类B中的成员函数能否引用基类A中的i,j,k?
答:因为B是A的派生类,i是A的公有成员,j是A的保护成员,k是A的私有成员,所以i,j能,k不能
(4)能否在main函数中通过C类对象c1引用基类A的成员i,j,k类B的成员?
答:因为C是A的派生类,i是A的公有成员,j是A的保护成员,k是A的私有成员, C是B的派生类,m是B的保护成员,n是B的私有成员,
所以在类外,只有i能引用
(5)能否在main函数中用C类对象c1以c1.f1(),c1.f2(),c1.f3(),c1.f4()的形式调用f1(),f2(),f3(),f4()?
答:因为C是A的派生类,f1()是A的公有成员函数,f2()是A的保护成员函数,f3()是B的公有成员函数,f4()是C的公有成员函数,所以在类外,只有f2()无法被调用
(6)派生类C的成员函数f4能否调用基类A的成员函数f1,f2及B类中的f3?
答:因为C是A的派生类,C是B的派生类,f1()是A的公有成员函数,f2()是A的保护成员函数,f3()是B的公有成员函数,所以都可以被调用
任务三:继承关系下,构造函数的调用顺序
#include <iostream>
using namespace std;
class A
{
public:
A(){a=0;b=0;}
A(int i){a=i;b=0;}
A(int i,int j){a=i;b=j;}
void display(){cout<<"a="<<a<<" b="<<b;}
private:
int a;
int b;
};
class B : public A
{
public:
B(){c=0;}
B(int i):A(i){c=0;}
B(int i,int j):A(i,j){c=0;}
B(int i,int j,int k):A(i,j){c=k;}
void display1()
{display();
cout<<" c="<<c<<endl;
}
private:
int c;
};
int main()
{ B b1;
B b2(1);
B b3(1,3);
B b4(1,3,5);
b1.display1();
b2.display1();
b3.display1();
b4.display1();
return 0;}
问题:
(1)阅读上述程序,写出运行时的输出结果;上机运行验证结果的正确性。
(2)对程序结果进行分析,重点要指出构造函数的调用过程
在main函数中,建立对象b1,b2,b3,b4,首先b1调用无参构造函数B(){c=0;},显示a=0, b=0,c=0的结果,b2调用带一个参数的构造函数B(int i):A(i){c=0;},显示出a=1, b=0,c=0的结果,b3调用带2个参数的构造函数B(int i,int j):A(i,j){c=0;},显示出a=1, b=3,c=0的结果,b4调用带3个参数的构造函数B(int i,int j,int k):A(i,j){c=k;},显示出a=1, b=3,c=5的结果
(3)为上述A、B类添加析构函数,并分析析构函数在继承关系下的调用顺序。
#include <iostream>
using namespace std;
class A
{
public:
A(){a=0;b=0;}
~A(){cout<<"A has been destructe!"<<endl;}
A(int i){a=i;b=0;}
A(int i,int j){a=i;b=j;}
void display(){cout<<"a="<<a<<" b="<<b;}
private:
int a;
int b;
};
class B : public A
{ public:
B(){c=0;}
~B(){cout<<"B has been destructe!"<<endl;}
B(int i):A(i){c=0;}
B(int i,int j):A(i,j){c=0;}
B(int i,int j,int k):A(i,j){c=k;}
void display1()
{display();
cout<<" c="<<c<<endl;
}
private:
int c;
};
int main()
{ B b1;
B b2(1);
B b3(1,3);
B b4(1,3,5);
b1.display1();
b2.display1();
b3.display1();
b4.display1();
return 0;
析构函数先调用B再调用A。
任务四:参照教材例6.1,定义Point(点)类,由Point类派生出Circle(圆)类,再由Circle类派生出Cylinder(圆柱体)类。写一个虚函数用于输出类族中各类的名字。分析如果该函数不是虚函数,输出又将是怎样?为什么?
#include"iostream"
using namespace std;
class point
{ public:
point(float a=0,float b=0);
void display_x();
void display_y();
protected:
float x,y;
};
point::point(float a,float b)
{ x=a;
y=b;
}
void point::display_x()
{ cout<< “x=”<<x<<endl;
}
void point::display_y()
{ cout<< “y=”<<y<<endl;
}
class circle : public point
{public:
circle(float a=0,float b=0,float c=0);
void display_radius();
virtual void display_area();
protected:
float r;
};
circle: : circle(float a,float b,float c):point(a,b),r(c){}
void circle::display_radius()
{ cout<<”r=”<< r<<endl;
}
void circle::display_area()
{ cout<< “circle area=”<<3.14*r*r<<endl;
}class cylinder:public circle
{
public:
cylinder(float a=0,float b=0,float c=0,float d=0);
void display_height();
void display_area();
void display_volume();
protected:
float h;};
cylinder::cylinder(float a,float b,float c,float d):circle(a,b,c),h(d){}
void cylinder::display_height()
{cout<< “height=”<<h<<endl;
}
void cylinder::display_area()
{cout<<” cylinder area=”<<2*3.14*r*r+2*3.14*r*h<<endl;
}
void cylinder::display_volume()
{cout<<” cylinder volume=”<< 3.14*r*r*h<<endl;
}
void main()
{
circle c1(1,2,3);
cylinder c2(1,2,3,4);
c1.display_x();
c1.display_y();
c1.display_radius();
c2.display_height();
c2.display_volume();
circle *p=&c1;
p->display_area();
p=&c2;
p->display_area();
}
如果该函数不是虚函数,则输出结果为:
因为当使pt指向cylinder,调用“p->display_area()”,但是没有定义虚函数,只能输出cylinder中基类的数据,只能调用circle的“p->display_area()”
任务五:建立一个建筑物类的层次体系。其中,基类building包括保护数据成员name(建筑物名称)、floors(层数)和areas(总面积),由building类派生住宅类house和办公楼类office;住宅类house包括私有数据成员rooms(房间数)和balcony(阳台数);办公楼类office包括私有数据成员offices(办公室数)和meetingrooms(会议室数)。住宅类house和办公楼类office都含有构造函数和print函数,以分别用于对数据成员的初始化和输出。在主函数中,实例化house类和office类对象并且将其数据输出
#include“iostream”
#include<string>
using namespace std;
class bulding
{protected:
string name;
int floors;
float areas;
public:
bulding(string,int,float);
void print();
};
bulding::bulding(string c,int n,
float s)
{name=c;floors=n;areas=s;}
void bulding::print()
{cout<<"name:"<<name<<"\nfloors:"
<<floors<<
"\nareas"<<areas<<"\n\n";}
class house:public bulding
{public:
house (string c,int n,float s,
int i,int j):bulding(c,n,s)
{rooms=i;
balcony=j;
}
void print();
private:
int rooms;
int balcony;
};
void house::print()
{cout<<"name:"<<name<<"\nfloors:"
<<floors<<"\nareas:"<<areas<<"\nrooms:"<< rooms<<"\nbalcony: "<<balcony<<endl;
}
class office:public bulding
{public:
office(string c,int n,float s,
int a,int b):bulding(c,n,s)
{offices=a;
meetingrooms=b;
}
void print();
private:
int offices;
int meetingrooms;
};
void office::print()
{cout<<"name:"<<name<<"\nfloors:"
<<floors<<"\nareas:"
<<areas<<"\noffices:"<<offices<<
"\nmeetingrooms:"
<<meetingrooms<<endl;
}
main()
{house c1("住宅",5,320,10,7 );
office c2("办公室",7,570,12,9);
c1.print();
c2.print();
return 0;
}
任务六:设计如图所示的学校师生类层次结构。第一层“在校人员”类的数据成员包括姓名、性别、出生日期、出生地和身份证号码。由“在校人员”类派生“学生类”和“教师类”。学生类的数据成员有学号、专业、班级和每周学时数。教师类的数据成员有工作证号、职称、课程和每周课时。助教类继承学生类和教师类,可以使用学生类的全部数据成员,以及教师类的课程和每周课时数据成员。
每个类提供自定义的构造函数和析构函数,定义一组公有成员函数分别用于置各数据成员的值和返回数据成员的值。特别地,同名函数print用于输出全部数据成员的值。
#include"iostream"
#include<string>
using namespace std;
class zaixiao
{public:
zaixiao(string nam,char s,int a,
string b,int c) {name=nam;sex=s;data=a;address=b;
id=c;}
protected:
string name;
char sex;
int data;
string address;
int id;
};
class teacher:virtual public
zaixiao
{public:
teacher(string nam,char s,int a,
string b,int c,string f,int g):zaixiao ( nam, s, a, b, c)
{ kecheng=f;
keshi=g; }
protected:
int workid;
string title;
string kecheng;
int keshi; };
class student:virtual public
zaixiao
{public:student(string nam,char s,int a,
string b,int c,int i,string j,
string k,int m):zaixiao( nam, s, a,
b, c)
{ xuehao=i; zhaungye=j;
banji=k; xueshi=m; }
protected:
int xuehao;
string zhaungye;
string banji;
int xueshi; };
class assintant:public teacher,
public student
{public:
assintant(string nam,char s,int a,
string b,int c,
int i,string j,string k,
int m,string
f,int g):zaixiao(nam,s,a,b,c),
student (nam,s, a,b,c,i,j,k,m),
teacher(nam,s,a,b,c,f,g) {}
void print()
{cout<<"name:"<<name<<endl;
cout<<"sex:"<<sex<<endl;
cout<<"data:"<<data<<endl;
cout<<"address:"<<address<<endl;
cout<<"id:"<<id<<endl;
cout<<"xuehao:"<<xuehao<<endl;
cout<<"banji:"<<banji<<endl;
cout<<"kecheng:"<<kecheng<<endl;
cout<<" keshi:"<< keshi<<endl;
}};
int main()
{assintant c1("张俊为",'f',
1992-10-31,"绍兴",33062419921031,
18,"电科","2班",48,"c++",32);
c1.print();
return 0; }
3总结或感悟(对运行结果所作的分析以及本次调试程序所取得的经验。如果程
序未能通过,分析其原因。)
通过本次试验,了解面向对象程序设计中继承性、多态性的概念;熟悉了单继承、多重继承中基类成员访问属性的变化规律及访问方法;掌握了类族中构造函数和析构函数的定义方法及调用顺序;知道了虚函数的定义和使用方法;理解公有继承下基类成员对派生类成员和派生类对象的可见性,能正确地访问继承层次中的各种类成员;
展开阅读全文