在程序界,有句话是,程序好些,bug难调。
很多bug并不一点是逻辑错误,而是一些细节问题。
我们分析下三个细节错误引起的无法运行问题:
1
|
//#define M_PI 3. 14159265358979323846 3.14中间有个空格
|
1
|
\t 写成了\ t 有个空格
|
首先,创建了一个新类型CFigure。我们想创建一些具体的图形(如,三角形、正方形或者圆),以及计算这些图形周长和面积的方法。但是,我们并不知道具体的图形是什么类型,所以无法用方法直接计算图形的这些特性。这就是要把CFigure类创建为抽象类的原因。抽象类是至少声明了一个虚方法的类,该虚方法没有实现,且其原型后面有=0。以这种方式声明的函数叫做纯虚函数。抽象类不能有对象,但是可以有继承类。因此可以实例化抽象类的指针和引用,然后从CFigure类派生出CTriangle、CSquare和CCircle类,分别表示三角形、正方形和圆形。
我们要实例化这些对象的类型,所以在这些派生类中,实现了FigureType方法、Circumference方法和Area方法。虽然这3个类中的方法名都相同,但是它们的实现不同,这与覆盖类似但含义不同。
如何理解?在本例的main函数中,声明了一个数组,内含3个CFigure类型的指针。作为指向基类的指针或引用,它们一定可以指向该基类的任何派生类。因此,可以创建一个CTriangle类型的对象,并设置CFigure类型的指针指向它,
1
|
CFigure* figures[3];
|
同理,用下面的代码可以设置其他图形:
1
2
3
|
figures[0] =
new
CTriangle(2.1,3.2,4.3);
figures[1] =
new
CSquare(5.4,6.6);
figures[2] =
new
CCircle(8.9);
|
现在,考虑下面的代码:
1
2
3
4
5
6
7
|
for
(
int
i = 0; i < 3; i++)
{
cout <<
"Figure type:\t"
<< figures[i]->FigureType();
cout<<
"\nCircumference:\t"
<< figures[i]->Circumference();
cout<<
"\nArea:\t\t"
<< figures[i]->Area();
cout<< endl << endl;
}
|
编译器将使用C++的动态绑定(dynamicbinding)特性,确定图形指针具体指向哪个类型的对象,调用合适的虚方法。只有把方法声明为虚方法,且通过指针或引用访问才能使用动态绑定。
全部代码如下,直接可以编译运行:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
#include "stdafx.h"
#include < iostream>
#include <tchar.h>
#define M_PI 3.14159265358979323846
using
namespace
std;
//#define M_PI 3. 14159265358979323846 3.14中间有个空格
class
CFigure
//base class
{
public
:
virtual
char
* FigureType() = 0;
virtual
double
Circumference() = 0;
virtual
double
Area() = 0;
virtual
~CFigure()
{
}
};
class
CTriangle :
public
CFigure
//Derived Class
{
public
:
CTriangle()
{
a = b = c = 0;
}
CTriangle(
double
a,
double
b,
double
c) : a(a), b(b), c(c) { }
virtual
char
* FigureType()
{
return
"Triangle"
;
}
virtual
double
Circumference()
{
return
a + b + c;
}
virtual
double
Area()
{
double
S = Circumference() / 2;
return
sqrt
(S * (S - a) * (S - b) * (S - c));
}
private
:
double
a, b, c;
};
class
CSquare :
public
CFigure
//Derived Class
{
public
:
CSquare()
{
a = 0.0;
b = 0.0;
}
CSquare(
double
a,
double
b) : a(a), b(b)
{
}
virtual
char
* FigureType()
{
return
"Square"
;
}
virtual
double
Circumference()
{
return
2 * a + 2 * b;
}
virtual
double
Area()
{
return
a * b;
}
private
:
double
a, b;
};
class
CCircle :
public
CFigure
//Derived Class
{
private
:
double
r;
public
:
CCircle()
{
r = 0;
}
CCircle(
double
r) : r(r)
{
}
virtual
char
* FigureType()
{
return
"Circle"
;
}
virtual
double
Circumference()
{
//return 2 * r * M_PI;
double
res = 0.00000000000000000000000;
res = 2 * r * M_PI;
//res = 2 * r * 3. 141592;
return
res;
}
virtual
double
Area()
{
double
res = 0.000000000000000000000;
res = 2 * r * M_PI;
//res = 2 * r * 3. 14159265358979323846;
return
res;
}
};
int
_tmain(
int
argc, _TCHAR* argv[])
{
CFigure* figures[3];
figures[0] =
new
CTriangle(2.1,3.2,4.3);
figures[1] =
new
CSquare(5.4,6.6);
figures[2] =
new
CCircle(8.9);
for
(
int
i = 0; i < 3; i++)
{
cout <<
"Figure type:\t"
<< figures[i]->FigureType();
cout<<
"\nCircumference:\t"
<< figures[i]->Circumference();
cout<<
"\nArea:\t\t"
<< figures[i]->Area();
cout<< endl << endl;
}
getchar
();
return
0;
}
|
运行结果:
本文转自 liam2199 博客,原文链接: http://blog.51cto.com/liam2199/1963425 如需转载请自行联系原作者