资源描述
实验1 类和对象
一、实验目的和要求
1.掌握声明类的方法,类和类的成员概念以及定义对象的方法;
2.掌握成员函数的实现与调用方法。;
3.掌握引检查和调试基于对象的程序的方法;
4. 深刻领会类与对象的区别,类实现数据隐藏与封装的原理等
二、实验内容
任务1:程序调试与程序设计
调试下列程序,程序描述了一个圆柱的类,成员中有私有数据半径r及高h,公有的成
员函数有构造函数与输出圆柱参数的函数,在main 函数中,输入两个参数,定义并初始化
此类的一个对象。
(1)请测试。
#include<iostream.h>
class column
{
private:
double r,h;
public:
column(double ri,double hi)
{
r=ri;
h=hi;
}
void prin()
{
cout<<"圆柱的高为:"<<h<<" 圆柱的半径为:"<<r<<endl;
}
};
int main()
{
column c(3,10);
c.prin();
return 0;
}
(2)再定义计算圆柱面积与体积的私有成员函数,在公有的成员函数prin 中调用,在
main 函数中输入半径r及高h,请设计程序并调试。
(3)在main 函数中也能以下列形式定义对象,请重新设计程序。
column c ;
任务2:程序设计
定义图书类,设图书信息包括书名、作者、出版社和定价属性,要求定义一
个类,用该类定义图书对象、通过函数成员为对象数据赋值、能输出图书属性。
任务3:程序设计
定义一个类,输入若干学生的学号,姓名和成绩,然后显示这个数据并计算
出平均分。同时设计出相应的程序进行测试。
任务4:程序设计
声明一个通讯录类,含姓名、地址、电话号码成员数据,其中姓名和电话号
码使用字符数组,地址使用字符型指针成员。要求如下成员函数:构造函数、拷
贝构造函数、析构函数、输出所有成员的函数。main()完成对象的定义和有关成
员函数的测试。
三、实验要求
(1)独立完成实验。
(2)实验前需先预先浏览实验指导书,编好源程序。
(3)实验过程中尽量独立思考,培养分析问题和解决问题的能力。
(4 )实验完毕后书写实验报告,实验报告内容包括:实验内容、结果分析以及本次实验的
心得体会。要求将程序源代码和运行时的输入输出数据情况书写在实验内容部分,并对程序
的输出结果进行分析,说明为什么能得出相应的结果(如果不能输出预期结果,需要分析说
明其原因)。
实验2 类的继承和派生
一、实验目的和要求
1、掌握利用单继承和多继承的方式定义派生类的方法。
2、深刻理解在各种继承方式下构造函数和析构函数的执行顺序。
3、理解和掌握公有继承、私有继承和保护继承对基类成员的访问机制。
4、理解虚基类的目的和作用。
二、实验内容
任务1:程序设计
声明一个圆类作为基类,含成员数据半径R;有成员函数:构造函数实现对基类成员数
据的初始化、计算圆面积的成员函数、输出的成员函数,要求输出圆半径R。把圆类作为基
类,通过公有继承,派生圆柱体类,派生类新增成员数据有高(H);新增成员函数有构造函
数、计算圆柱体体积的函数、输出所有成员的函数。main()完成派生类对象的定义和相关函
数的测试。
任务2:程序设计
声明一个学生类,有成员函数:学号、姓名、性别、年龄,要求有如下成员函数:构造
函数,输出所有成员的函数。声明一个课程类,有成员数据:课程编号、课程名称、学时数,
要求有如下成员函数:构造函数,输出所有成员的函数。将学生类和课程类作为基类,通过
公有继承,派生选课类,派生类新增成员数据有:成绩;新增成员函数有:构造函数,输出
所有成员的函数。main()完成派生类对象的定义和相关函数的测试。
任务3:程序设计
设计一个汽车类Vehicle,包含数据成员车轮和重量,由它派生出类Car 和
类Truck,前者包含载客数,后者包含载重量。编写程序实现。
三、实验要求
(1)独立完成实验。
(2)实验前需先预先浏览实验指导书,编好源程序。
(3)实验过程中尽量独立思考,培养分析问题和解决问题的能力。
(4 )实验完毕后书写实验报告,实验报告内容包括:实验内容、结果分析以及本次实验的
心得体会。要求将程序源代码和运行时的输入输出数据情况书写在实验内容部分,并对程序
的输出结果进行分析,说明为什么能得出相应的结果(如果不能输出预期结果,需要分析说
明其原因)。
实验3 虚函数和多态性
一、实验目的和要求
1、理解动态联编的概念及多态性的实现方法。
2、理解虚函数和纯虚函数的概念并掌握它们的使用方法。
3、理解和掌握抽象类的使用。
二、实验内容
任务1:程序设计
上机运行下面程序,然后利用关键字virtual来指明函数calcTuition()为虚函数,观
察运行结果,比较添加virtual 前后的运行结果,理解多态性的概念。
#include<iostream.h>
class Student
{
public:
//....
void clacTuition() //计算学费
{
cout<<"计算学生学费"<<endl;
}
};
class GraduateStudent :public Student
{
public:
//...
void calcTuition()
{
cout<<"计算研究生学费"<<endl;
}
};
void fn(Student& x)
{
x.calcTuition();
}
void main()
{
Student s;
GraduateStudent gs;
fn(s); //计算一下学生s 的学费
fn(gs); //计算一下研究生gs 的学费
}
任务2:程序设计
更改下列程序,使其运行结果为:
Calling test(bc)
In Base class, int x=1
In Base class, int x=1
Calling test(sc)
In SubClass, float x=1
In SubClass, float x=2
程序:
#include <iostream.h>
class Base{
public:
virtual void fn(int x)
{
cout <<"In Base class, int x = " <<x <<endl;
}
};
class SubClass :public Base{
public:
virtual void fn(float x)
{
cout <<"In SubClass, float x = " <<x <<endl;
}
};
void test(Base& b)
{
int i =1;
b.fn(i);
float f =2.0;
b.fn(f);
}
void main()
{
Base bc;
SubClass sc;
cout <<"Calling test(bc)\n";
test(bc);
cout <<"Calling test(sc)\n";
test(sc);
}
任务3:程序设计
更改下列程序,使其运行结果为:
This is Base class
This is SubClass
程序:
class SubClass :public Base{
public:
SubClass afn()
{
cout <<"This is SubClass.\n";
return this;
}
};
void test(Base& x)
{
Base* b;
b = x.afn();
}
void main()
{
Base bc;
SubClass sc;
test(bc);
test(sc);
}
任务4:程序设计
上机分析下面程序,掌握抽象类、纯虚函数以及动态绑定。
// shape.h 文件 定义抽象基类Shape
#ifndef SHAPE_H
#define SHAPE_H
#include <iostream.h>
class Shape
{
public:
virtual double Area() const
{
return 0.0;
}
// 纯虚函数,在派生类中重载
virtual void PrintShapeName() const = 0;
virtual void Print() const = 0;
};
#endif
// point.h 文件 定义类Point
#ifndef POINT_H
#define POINT_H
#include "shape.h"
class Point : public Shape
{
int x, y; //点的x 和y 坐标
public:
Point( int = 0, int = 0 ); // 构造函数
void SetPoint( int a, int b ); // 设置坐标
int GetX() const // 取x 坐标
{
return x;
}
int GetY() const // 取y 坐标
{
return y;
}
virtual void PrintShapeName() const
{
cout << "Point: ";
}
virtual void Print() const; //输出点的坐标
};
#endif
// Point.cpp 文件 Point 类的成员函数定义
#include <iostream.h>
#include "point.h"
Point::Point( int a, int b ) : x( a ), y( b )
{}
void Point::SetPoint( int a, int b )
{
x = a;
y = b;
}
void Point::Print() const
{
cout << '[' << x << ", " << y << ']';
}
// circle.h 定义类Circle
#ifndef CIRCLE_H
#define CIRCLE_H
#include <iostream.h>
#include "point.h"
class Circle : public Point
{
double radius;
public:
Circle(int x = 0, int y = 0, double r = 0.0);
void SetRadius( double r ); //设置半径
double GetRadius() const; //取半径
virtual double Area() const; //计算面积a
virtual void Print() const; //输出圆心坐标和半径
virtual void PrintShapeName() const
{
cout << "Circle: ";
}
};
#endif
// circle.cpp 文件 circle 类的成员函数定义
#include "circle.h"
Circle::Circle(int a,int b,double r): Point(a,b), radius( r )
{
}
void Circle::SetRadius( double r )
{
radius = ( r >= 0 ? r : 0 );
}
double Circle::GetRadius() const
{
return radius;
}
double Circle::Area() const
{
return 3.14159 * radius * radius;
}
void Circle::Print() const
{
cout << "Center = ";
Point::Print();
cout << "; Radius = " << radius << endl;
}
//main.cpp 文件演示图形类
#include <iostream.h>
#include "shape.h"
#include "point.h"
#include "circle.h"
void virtualViaPointer( const Shape * );
void virtualViaReference( const Shape & );
int main()
{
//创建point、circle 对象
Point point(30,50);
Circle circle(120,80,10.0);
//输出point、circle、rectangle 对象信息
point.PrintShapeName();
point.Print();
cout << endl;
circle.PrintShapeName();
circle.Print();
//定义基类对象指针
Shape *arrayOfShapes[2];
arrayOfShapes[ 0 ] = &point;
arrayOfShapes[ 1 ] = &circle;
//通过基类对象指针访问派生类对象
cout << "Virtual function calls made off " << "base-class pointers\n";
for ( int i = 0; i < 2; i++ )
virtualViaPointer( arrayOfShapes[ i ] );
cout << "Virtual function calls made off " << "base-class references\n";
for ( int j = 0; j < 2; j++ )
virtualViaReference( *arrayOfShapes[ j ] );
return 0;
}
//通过基类对象指针访问虚函数实现动态绑定
void virtualViaPointer( const Shape *baseClassPtr )
{
baseClassPtr->PrintShapeName();
baseClassPtr->Print();
cout << "Area = " << baseClassPtr->Area() << endl;
}
//通过基类对象引用访问虚函数实现动态绑定
void virtualViaReference( const Shape &baseClassRef )
{
baseClassRef.PrintShapeName();
baseClassRef.Print();
cout << "Area = " << baseClassRef.Area() << endl;
}
任务5:程序设计
仿照前面的例子,设计一个计算图形面积的类库。
类库的顶层是一个抽象类,并且提供三个纯虚函数;显示数据成员、返回面积和返回体
积。
class Shape
{
virtual void showData()=0;
virtual double reArea()=0;
virtual double reVolume()=0;
};
第二层由Shape 类派生TwoDimShape (二维图形)和ThreeShape (三维图形),它们增
加了有关的数据成员,但没有成员函数的实现。
第三层派生具体的图形类。TwoDimShape 类派生Circle (圆)、Elipse (椭圆)、Rectangle
(矩形)和Triangle (三角形)等类。ThreeShape 类派生Ball (球体)、Cylinder (圆柱体)、
RectangularParallelepiped (长方体)等类。
在主函数测试中使用多态方式调用不同对象的求值函数。
三、实验要求
(1)独立完成实验。
(2)实验前需先预先浏览实验指导书,编好源程序。
(3)实验过程中尽量独立思考,培养分析问题和解决问题的能力。
(4 )实验完毕后书写实验报告,实验报告内容包括:实验内容、结果分析以及本次实验的
心得体会。要求将程序源代码和运行时的输入输出数据情况书写在实验内容部分,并对程序
的输出结果进行分析,说明为什么能得出相应的结果(如果不能输出预期结果,需要分析说
明其原因)。
实验4 运算符重载
一、实验目的和要求
(1) 掌握运算符重载的概念和应用。
(2) 掌握用成员函数、友元函数重载运算符的特点。
(3) 理解一些特殊运算符的重载。
二、实验内容
(1) 将以下程序更改为友元函数重载的形式并上机运行。
#include<iostream.h>
class RMB{ //人民币类
public:
RMB(double d){ yuan=d; jf=(d-yuan)/100; }
RMB interest(double rate); //计算利息
RMB add(RMB d); //人民币加
void display(){ cout <<(yuan + jf / 100.0) << endl; }
RMB operator+(RMB d){ return RMB(yuan+d.yuan+(jf+d.jf)/100); }
//人民币加的运算符重载
RMB operator*(double rate){ return RMB((yuan+jf/100)*rate);}
private:
unsigned int yuan; //元
unsigned int jf; //角分
};
RMB RMB::interest(double rate)
{
return RMB((yuan + jf / 100.0) * rate);
}
RMB RMB::add(RMB d)
{
return RMB(yuan + d.yuan + jf / 100.0 + d.jf / 100.0);
}
//以下是计算应付人民币的两个版本
RMB expense1(RMB principle, double rate)
{
RMB interest = principle.interest(rate);
return principle.add(interest);
}
RMB expense2(RMB principle, double rate)
{
RMB interest = principle * rate; //本金乘利息
return principle + interest; //连本带利
}
void main()
{
RMB x = 10000.0;
double yrate = 0.035;
expense1(x,yrate).display();
expense2(x,yrate).display();
}
(2) 将以下程序中重载运算符定义函数的返回类型更改(值返回更改为引用返回,引用
返回更改为值返回),观察程序运行结果,说明原因。
#include<iostream.h>
class RMB{
public:
RMB(unsigned int d, unsigned int c);
friend RMB operator +(RMB&, RMB&);
friend RMB& operator ++(RMB&);
void display(){ cout <<(yuan + jf / 100.0) << endl; }
protected:
unsigned int yuan;
unsigned int jf;
};
RMB::RMB(unsigned int d, unsigned int c)
{
yuan = d;
jf = c;
while ( jf >=100 ){ //以使构造时,确保角分值小于100
yuan ++;
jf -= 100;
}
}
RMB operator+(RMB& s1, RMB& s2) // 此处改为RMB& operator+(RMB& s1, RMB& s2)
{
unsigned int jf = s1.jf + s2.jf;
unsigned int yuan = s1.yuan + s2.yuan;
RMB result( yuan, jf );
return result;
}
RMB& operator ++(RMB& s) //此处改为RMB operator ++(RMB& s)
{
s.jf ++;
if(s.jf >= 100){
s.jf -= 100;
s.yuan++;
}
return s;
}
void main()
{
RMB d1(1, 60);
RMB d2(2, 50);
RMB d3(0, 0);
d3 = d1 + d2;
++d3;
d3.display();
}
(3) 上机分析下面程序,掌握运算符重载的方法。
#include <iostream.h>
class Complex
{
friend Complex operator+( const double &d, const Complex &c );
friend Complex operator-( const double &d, const Complex &c );
double m_fReal, m_fImag;
public:
Complex( const double &r = 0, const double &i = 0): m_fReal( r ), m_fImag( i )
{}
Complex( const Complex &c ): m_fReal( c.m_fReal ), m_fImag( c.m_fImag )
{}
double GetReal() const
{
return m_fReal;
}
double GetImag() const
{
return m_fImag;
}
Complex& operator=( const Complex &c )
{
if( this == &c )
{
return *this;
}
m_fReal=c.m_fReal;
m_fImag=c.m_fImag;
return *this;
}
Complex operator+( const Complex &c )
{
return Complex( m_fReal+c.m_fReal, m_fImag+c.m_fImag );
}
Complex operator-( const Complex &c )
{
return Complex( m_fReal-c.m_fReal, m_fImag-c.m_fImag );
}
Complex operator+( const double &d )
{
return Complex( m_fReal+d, m_fImag );
}
Complex operator-( const double &d )
{
return Complex( m_fReal-d, m_fImag );
}
};
Complex operator+( const double &d, const Complex &c )
{
return Complex( d + c.m_fReal, c.m_fImag );
}
Complex operator-( const double &d, const Complex &c )
{
return Complex( d - c.m_fReal, c.m_fImag );
}
int main()
{
Complex c1( 3.3, 4.4 );
Complex c2( 5.5, 2.2 );
Complex c3;
c3 = c1 + c2;
cout << "C3 = " << c3.GetReal() << "+i" << c3.GetImag() << endl;
c3 = c1 - c2;
cout << "C3 = " << c3.GetReal() << "+i" << c3.GetImag() << endl;
c3 = c1 + c2;
cout << "C3 = " << c3.GetReal() << "+i" << c3.GetImag() << endl;
c3 = c1 + 1.1;
cout << "C3 = " << c3.GetReal() << "+i" << c3.GetImag() << endl;
c3 = c1 - 1.1;
cout << "C3 = " << c3.GetReal() << "+i" << c3.GetImag() << endl;
c3 = 9.9 + c1;
cout << "C3 = " << c3.GetReal() << "+i" << c3.GetImag() << endl;
c3 = 9.9 - c1;
cout << "C3 = " << c3.GetReal() << "+i" << c3.GetImag() << endl;
( c3 = c1 ) = c2;
cout << "C3 = " << c3.GetReal() << "+i" << c3.GetImag() << endl;
return 0;
}
注意重载“=”运算符的方法:首先应判断是否是自身赋值,其次应注意返回值是引用,这
是为了支持( c3 = c1 ) = c2这种用法。
(4) 完善下列程序,利用运算符重载的形式使之能够实现矩阵类Matrix 的加减乘 (+-*)及
赋值(=)运算。
//头文件MatrixException.h
#include <stdexcept>
#include <string>
using namespace std;
class MatrixException : public logic_error
{
public:
MatrixException(const string& s) : logic_error(s)
{}
};
class Singular: public MatrixException
{
public:
Singular(const string& s) : MatrixException("Singular: "+s)
{}
};
class InvalidIndex: public MatrixException
{
public:
InvalidIndex(const string& s) : MatrixException("Invalid index: "+s)
{}
};
class IncompatibleDimension: public MatrixException
{
public:
IncompatibleDimension(const string& s) : MatrixException("Incompatible Dimensions:
"+s)
{}
};
//头文件Matrix.h
#include "MatrixException.h"
class Matrix
{
double* elems; // 存放矩阵中各元素,按行存放
int row, col; // 矩阵的行与列
protected:
double rowTimesCol(int i, const Matrix &b, int j ) const; /矩阵的第i行矩阵b 的
第j列相乘
public:
Matrix(int r, int c);
Matrix(double* m, int r, int c);
Matrix( const Matrix &m );
~Matrix();
//重载运
展开阅读全文