C++编程范式:虚函数、面向对象与泛型编程解析
立即解锁
发布时间: 2025-08-22 00:46:11 阅读量: 4 订阅数: 22 


C++编程语言第三版:全面解析与实践
### C++编程范式:虚函数、面向对象与泛型编程解析
#### 1. 虚函数
虚函数机制中的虚函数表(vtable)能确保在调用者不了解对象大小和数据布局的情况下,对象仍可被正确使用。调用者只需知道虚函数表在栈中的位置,以及每个虚函数对应的索引。这种虚调用机制的效率与“普通函数调用”机制基本相当,其空间开销为:包含虚函数的类的每个对象中有一个指针,以及每个此类有一个虚函数表。
#### 2. 面向对象编程
数据抽象是优秀设计的基础,贯穿于编程的始终。然而,仅靠用户自定义类型往往不够灵活,难以满足实际需求。下面我们将探讨简单用户自定义数据类型存在的问题,以及如何通过类层次结构来解决这些问题。
##### 2.1 具体类型的问题
具体类型就像通过模块定义的“伪类型”,如同一个黑盒。一旦黑盒定义完成,它与程序的其他部分几乎没有交互。除非修改其定义,否则无法将其应用于新的用途。这种情况有时是理想的,但也可能导致严重的不灵活性。
以图形系统中定义的`Shape`类型为例,假设系统需要支持圆形、三角形和正方形,同时我们有以下定义:
```cpp
class Point{ /* ... */ };
class Color{ /* ... */ };
```
我们可能会这样定义`Shape`:
```cpp
enum Kind { circle, triangle, square }; // 枚举 (§4.8)
class Shape {
Kind k; // 类型字段
Point center;
Color col;
// ...
public:
void draw();
void rotate(int);
// ...
};
```
“类型字段”`k`用于让`draw()`和`rotate()`等操作确定它们处理的是哪种形状。`draw()`函数可能会这样定义:
```cpp
void Shape::draw()
{
switch (k) {
case circle:
// draw a circle
break;
case triangle:
// draw a triangle
break;
case square:
// draw a square
break;
}
}
```
这种实现方式存在很多问题。像`draw()`这样的函数必须“了解”所有形状的类型。因此,每次向系统中添加新形状时,此类函数的代码都会增加。如果定义了新形状,必须检查并(可能)修改对形状的每个操作。除非能够访问每个操作的源代码,否则无法向系统中添加新形状。由于添加新形状需要“触及”形状的每个重要操作的代码,这需要高超的技能,并且可能会在处理其他(旧)形状的代码中引入错误。特定形状的表示选择可能会受到严重限制,因为(至少部分)它们的表示必须适应由一般类型`Shape`定义的通常固定大小的框架。
##### 2.2 类层次结构
问题在于,没有区分每个形状的通用属性(例如,形状有颜色,可以绘制等)和特定形状的属性(例如,圆形有半径,由圆形绘制函数绘制等)。表达并利用这种区别就是面向对象编程的核心。支持这种区别表达和使用的语言支持面向对象编程,其他语言则不支持。
继承机制(从Simula引入C++)提供了解决方案。首先,我们定义一个类来定义所有形状的通用属性:
```cpp
class Shape {
Point center;
Color col;
// ...
public:
Point where() { return center; }
void move(Point to) { center = to; /* ... */ draw(); }
virtual void draw() = 0;
virtual void rotate(int angle) = 0;
// ...
};
```
与抽象类型`Stack`(§2.5.4)一样,那些可以定义调用接口但尚未能定义实现的函数是虚函数。特别是,`draw()`和`rotate()`函数只能针对特定形状进行定义,因此它们被声明为虚函数。
基于这个定义,我们可以编写操作形状指针向量的通用函数:
```cpp
void ro
```
0
0
复制全文
相关推荐










