在程序界,有句话是,程序好些,bug难调。

很多bug并不一点是逻辑错误,而是一些细节问题。

我们分析下三个细节错误引起的无法运行问题:

//#defineM_PI3.141592653589793238463.14中间有个空格

\t写成了\t有个空格

首先,创建了一个新类型CFigure。我们想创建一些具体的图形(如,三角形、正方形或者圆),以及计算这些图形周长和面积的方法。但是,我们并不知道具体的图形是什么类型,所以无法用方法直接计算图形的这些特性。这就是要把CFigure类创建为抽象类的原因。抽象类是至少声明了一个虚方法的类,该虚方法没有实现,且其原型后面有=0。以这种方式声明的函数叫做纯虚函数。抽象类不能有对象,但是可以有继承类。因此可以实例化抽象类的指针和引用,然后从CFigure类派生出CTriangle、CSquare和CCircle类,分别表示三角形、正方形和圆形。

我们要实例化这些对象的类型,所以在这些派生类中,实现了FigureType方法、Circumference方法和Area方法。虽然这3个类中的方法名都相同,但是它们的实现不同,这与覆盖类似但含义不同。

如何理解?在本例的main函数中,声明了一个数组,内含3个CFigure类型的指针。作为指向基类的指针或引用,它们一定可以指向该基类的任何派生类。因此,可以创建一个CTriangle类型的对象,并设置CFigure类型的指针指向它,

CFigure*figures[3];

同理,用下面的代码可以设置其他图形:

figures[0]=newCTriangle(2.1,3.2,4.3);figures[1]=newCSquare(5.4,6.6);figures[2]=newCCircle(8.9);

现在,考虑下面的代码:

for(inti=0;i<3;i++){cout<<"Figuretype:\t"<<figures[i]->FigureType();cout<<"\nCircumference:\t"<<figures[i]->Circumference();cout<<"\nArea:\t\t"<<figures[i]->Area();cout<<endl<<endl;}

编译器将使用C++的动态绑定(dynamicbinding)特性,确定图形指针具体指向哪个类型的对象,调用合适的虚方法。只有把方法声明为虚方法,且通过指针或引用访问才能使用动态绑定。


全部代码如下,直接可以编译运行:

#include"stdafx.h"#include<iostream>#include<tchar.h>#defineM_PI3.14159265358979323846usingnamespacestd;//#defineM_PI3.141592653589793238463.14中间有个空格classCFigure//baseclass{public:virtualchar*FigureType()=0;virtualdoubleCircumference()=0;virtualdoubleArea()=0;virtual~CFigure(){}};classCTriangle:publicCFigure//DerivedClass{public:CTriangle(){a=b=c=0;}CTriangle(doublea,doubleb,doublec):a(a),b(b),c(c){}virtualchar*FigureType(){return"Triangle";}virtualdoubleCircumference(){returna+b+c;}virtualdoubleArea(){doubleS=Circumference()/2;returnsqrt(S*(S-a)*(S-b)*(S-c));}private:doublea,b,c;};classCSquare:publicCFigure//DerivedClass{public:CSquare(){a=0.0;b=0.0;}CSquare(doublea,doubleb):a(a),b(b){}virtualchar*FigureType(){return"Square";}virtualdoubleCircumference(){return2*a+2*b;}virtualdoubleArea(){returna*b;}private:doublea,b;};classCCircle:publicCFigure//DerivedClass{private:doubler;public:CCircle(){r=0;}CCircle(doubler):r(r){}virtualchar*FigureType(){return"Circle";}virtualdoubleCircumference(){//return2*r*M_PI;doubleres=0.00000000000000000000000;res=2*r*M_PI;//res=2*r*3.141592;returnres;}virtualdoubleArea(){doubleres=0.000000000000000000000;res=2*r*M_PI;//res=2*r*3.14159265358979323846;returnres;}};int_tmain(intargc,_TCHAR*argv[]){CFigure*figures[3];figures[0]=newCTriangle(2.1,3.2,4.3);figures[1]=newCSquare(5.4,6.6);figures[2]=newCCircle(8.9);for(inti=0;i<3;i++){cout<<"Figuretype:\t"<<figures[i]->FigureType();cout<<"\nCircumference:\t"<<figures[i]->Circumference();cout<<"\nArea:\t\t"<<figures[i]->Area();cout<<endl<<endl;}getchar();return0;}

运行结果: