//采用动态联编,易于编程人员编写 Square(int edg); ~Square() { } }; Square::Square(int edg) { edge=edg; } //求正方形的面积 double Square::GetArea() { double result; result=edge*edge; reture result; }
//下面的全局函数是专门为了 //动态调用虚函数而设计的 //函数体的声明在源代码的最后面 void objGetArea(Square* base); class Rectangle:public Square { protected: int length; //它的宽由正方形类Square的成员提供 public: double GetArea(); Rectangle(int edg,int leng); ~Rectangle() { } }; //求矩形的面积 double Rectangle::GetArea() { double result; result=length*edge; return result; } //这里由于edge是公有继承基类Square的 //protected对象,因此可直接调用。 Rectangle::Rectangle(int edg,int leng):Square(int edg) { //这里采用成员列表的形式初始化类的成员 //Square(int edg)调用基类的构造函数 //使edge=edg; length=leng; }
void objGetArea(Square* obj) { obj->GetArea(); } 在SquareRectangle.cpp中给出主函数main()的源代码: //SquareRectangle.cpp #include<iostream.h> #include<math.h> #include<SquareRectangle.h> main() { Square Squa1(100); //调用Square::Square(int)初始化 Rectangle Rect(200,300); //调用Rectangle::Rectangle(int,int)初始化 //比较下面两个语句 cout<<"正方形Squa1(100)的 面积为:"<<Squa1.GetArea()<<endl; //输出为:10000 cout<<"正方形Squa1(100)的 面积为:"<<objGetArea(&Squa1)<<endl; //输出为:10000 //比较下面两个语句 cout<<"派生矩形 Rect(200,300) 的 面积为::"<<Rect.GetArea()<<endl; //输出为60000 cout<<"派生矩形 Rect(200,300) 的 面积为::"<<objGetArea(&Rect)<<endl; //输出为60000 } 注意:使用虚函数要注意的地方是,不要在引用虚函数的时候,采用作用符:或者是::,这样就可能会变 成静态联编,根本不能表现虚函数的优越性。所以我们在调用虚函数时,通常采用的是指针或引用。就像 是上例中的全局函数objGetArea(Square* obj)一样,编译系统会根据实际情况确定是哪一个类在调用虚函 数,如果是采用作用符,就失去了虚函数的意义了,就像在主程序中要求比较的四个语句一样,其中一个是 动态连编,一个是静态连编。另外,参数传递时要注意一一对应,在调用objGetArea(Square*)时,一定要 在类Squa或Rect前面加&,表示是类Squa或Rect的地址,这样才与指针相对应。 实验思考:除了用全局函数来调用虚函数外,大家还能用别的方法吗?试编写一例。
实验三 运算符的重载 实验目的: 了解运算俯重载的基础知识; 学会运算符重载的编程。 实验内容: 为complex复数类重载+、++以及*三个友元运算符,并在主程序中进行简单的验算,要求要考虑周全。 分析:大家只要了解了运算符重载的语法,就不难编出程序了。下面给出源代码: 类的声明文件放在complex.h里面。 #include <iostream.h> #include<math.h> class complex { private: double re, im;//定义实部和虚部 public: complex (double r=1.0 , double i=1.0 ) { re=r; im=i; } friend complex operator + ( complex &, complex &); friend complex operator + ( double, complex& ); friend complex operator + ( complex &, double ); friend void operator ++ ( complex&); friend complex operator * ( complex &, complex &);
void print() { cout<<"("<<complex.rm<<","<<complex.y <<")"<<endl; } };
complex operator +( complex &a, complex &b ) { return complex ( a.re + b.re, a.im + b.im ); } complex operator +( double a, complex &b ) { return complex ( a.+ b.re, a+ b.im ); } complex operator +( complex &a, double b ) { return complex ( a.re + b, a.im + b ); } void operator ++( complex& a) { a.re ++; a.im ++; } complex operator *( complex &a, complex &b ) { return complex ( a.re * b.re - a.im * b.im, a.re * b.im + a.im*b.re ); } //这里用的公式是:(A+Bi)*(C+Di)= //(AC-BD)+(AD+BC)i 说明: 复数类complex定义了两个基本对象,一个作为实部,一个作为虚部。除了构造函数外, 还定义了五个友员函数,分别用来重载+、++和*,其中前面三个友员函数用来重载+,考虑到实 数+复数和复数+实数两种情况,所以共用了三个友员函数;后面两个重载++和*;print()函数输 出该复数。 主程序放在complex.cpp中: main() { const complex num1 (1, 0); //num1 = (1.000, 0.000) complex num2 (3., 8.); //num2 = (3.000, 8.000) complex num3; //num3 = (1.000, 1.000) complex num4(5, 5); //num4 = (5.000, 5.000)
double x = 1.0; double y = 5.0;
num3=num1+num2; num3.print(); //prints out (4.000, 8.000) num3++; num3.print(); //print out (5.000,9.000) complex num5=num4+x; num5.print(); //prints out (6.000, 6.000) complex num6=y+num4; num6.print(); //prints out (10.000, 10.000) complex num7=num2*num3; num7.print(); //prints out (-57.000, 67.000) }
说明:主程序共声明了7个complex对象,其中num1到num4是采用赋初值的方法赋值的。num3的 赋值看complex的构造函数,当出现complex num3这种语句时,构造函数便使re和im等于括号中 赋给的初值,即re=1.0和im=1.0。当num3=num1+num2之后,num3的值便改变成(1.0,0)+(3.0,8.0), 在num3++之后,num3的实部和虚部就分别加1。num5和num6是为了实现实数和复数相加。 num7=num2*num3,即num7=(3,8)*(5,9)。然后将各值分别输出。 注意:运算符成员函数只能定以运算符的含义,不能改变运算符的优先级和解和顺序;可以定义 多个同名的运算符函数。但参数类型应有差别,否则会有二义性。 实验思考:这里只给出了+、++和*的重载,大家可以在下面练习-、--和/的重载,如果有兴趣的 话,还可以练习赋值符=、+=等等的重载。
实验四 综合练习 实验目的: 全面了解面向对象程序设计的设计方法; 对继承、虚函数、多态性有更深一步的了解; 学会编制结构清晰、风格良好、符合C++语言风格的C++程序。 实验内容: 设计一个可在屏幕上作图的简单实例,要求是不必真正在屏幕上实现作图,只是有一个示意即可。例 如:画一个矩形,不必真正画出矩形,只需输出一句话:This is a rectangle !即可。要用到继承,虚函数, 多态,数据的封装,构造函数的实现等等各种面向对象程序设计的特性。 提示: 我们可以设计一个point类,指明屏幕上特定点的位置,其他的各个类都可以使用它。再设计一个基 类Shape类,然后在Shpae类的基础上派生出各种类,如直线类line,矩形类Rectangle,圆类circle以及分 |