### 关于 Win32 平台上 "pure virtual function call" 的解释 本文旨在详细解析在 Win34 平台上调用纯虚函数时所发生的情况。通过一个具体示例,我们将深入探讨编译器如何处理纯虚函数调用以及为什么会触发 "pure virtual function call" 的错误提示。 #### 0. 引言 在 C++ 中,虚函数允许子类重写父类的方法,从而实现多态性。当一个虚函数没有具体的实现时,它被称为纯虚函数。在本篇文章中,我们将不讨论为什么会出现 "pure virtual function call" 错误提示或如何触发该错误,而是将重点放在当直接或间接地在构造函数或析构函数中调用纯虚函数时,程序本身的行为上。本文将详细介绍 Win32 平台上这一行为的具体表现。 #### 1. 示例代码 示例代码定义了一个名为 `Shape` 的基类,其中包含一个纯虚函数 `area()`。此外,还定义了一个派生类 `Rectangle`,它继承自 `Shape` 类,并实现了 `area()` 方法。然而,在 `Shape` 类的构造函数中,尝试间接调用了未被实现的 `area()` 方法。 ```cpp class Shape { private: double ValuePerSquareUnit; protected: Shape(double valuePerSquareUnit) : ValuePerSquareUnit(valuePerSquareUnit) { std::cout << "creating shape, value=" << value() << std::endl; } public: virtual double area() const = 0; double value() const { return ValuePerSquareUnit * area(); // 间接调用纯虚函数 } virtual ~Shape() { printf("Shape::~Shape() is called\n"); } double getPerSquareUnit() { return ValuePerSquareUnit; } }; class Rectangle : public Shape { private: double Width; double Height; public: Rectangle(double width, double height, double valuePerSquareUnit) : Shape(valuePerSquareUnit), Width(width), Height(height) {} virtual double area() const { return Width * Height; } }; ``` #### 2. 汇编代码分析 为了更好地理解编译器是如何处理纯虚函数调用的,我们需要查看汇编代码。在编译阶段,编译器会为每个类创建一个虚函数表(vtable),其中包括指向各个虚函数的指针。当尝试调用纯虚函数时,编译器会在 vtable 中查找对应的函数地址,但由于纯虚函数没有实现,因此该地址是空的。此时,程序将调用 `_purecall` 函数,触发错误提示。 #### 3. 虚函数表 虚函数表是一个重要的概念,在 C++ 中用于支持动态绑定。对于 `Shape` 类,其虚函数表包含指向 `area()` 和 `~Shape()` 的指针。由于 `area()` 是纯虚函数,因此其对应的地址为空。这意味着当程序尝试调用 `area()` 时,会访问一个无效的内存位置。 #### 4. `_purecall` 函数及其汇编代码 当编译器检测到对纯虚函数的调用时,会调用 `_purecall` 函数。这是一个特殊的函数,用于处理此类错误情况。在汇编代码层面,我们可以看到 `_purecall` 的具体实现细节,这有助于我们理解错误是如何被触发的。 #### 5. 错误消息来源 错误消息通常是由 `_purecall` 函数触发的。在运行时系统中,有一个宏 `RT_PUREVIRT` 用来定义错误类型,另一个宏 `RT_PUREVIRT_TXT` 用来定义错误消息文本。此外,还有一个数组 `rterrs` 存储了所有可能的错误消息。当 `_purecall` 被调用时,它会根据这些宏和数组来显示错误消息。 #### 6. 显示错误消息的函数 显示错误消息的功能由 `_NMSG_WRITE` 函数完成。当 `_purecall` 被调用时,它会调用 `_NMSG_WRITE` 来输出错误消息。此外,我们还可以查看调用栈,了解错误发生的具体上下文。 #### 7. 当纯虚函数显式实现时会发生什么? 当纯虚函数在类内部或外部被显式实现时,程序的行为将有所不同: - **7.1 在类内部实现**: - 如果在 `Shape` 类内部实现 `area()` 方法,那么编译器将不再报错,因为纯虚函数已经被具体实现。 - **7.2 在类外部实现**: - 另一种方法是在类外部实现 `area()` 方法。这种情况下,只要确保在任何派生类中都正确地实现了 `area()`,就不会触发错误。 #### 8. 总结 本文通过一个具体的示例解释了在 Win32 平台上调用纯虚函数时可能发生的情况。我们深入了解了编译器如何处理这种情况、错误消息的来源以及如何避免错误的发生。对于 C++ 开发者来说,理解这些概念对于编写健壮且可维护的代码至关重要。
剩余11页未读,继续阅读
- 粉丝: 1585
- 资源: 17
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助