ZBLOG

delete 一个抽象类指针时,发生“pure virtual method called”异常?

当你在删除一个抽象类指针时遇到 “pure virtual method called” 异常,通常是因为在对象的析构过程中调用了纯虚函数。以下是原因分析和解决方法:


1. 问题原因

  • 析构顺序问题
    当派生类对象通过基类(抽象类)指针被删除时,会先调用派生类的析构函数,再调用基类的析构函数。
    如果在基类析构函数中(直接或间接)调用了纯虚函数,就会触发此异常。

  • 典型场景

    • 基类的析构函数中调用了某个虚函数,而该虚函数在派生类中已被覆盖为纯虚函数。
    • 在多线程环境中,对象可能在析构过程中被其他线程访问。

2. 示例代码(错误场景)

  1. class AbstractBase {
  2. public:
  3. virtual ~AbstractBase() {
  4. // 错误:在基类析构中调用纯虚函数
  5. pureVirtual();
  6. }
  7. virtual void pureVirtual() = 0; // 纯虚函数
  8. };
  9. class Derived : public AbstractBase {
  10. public:
  11. void pureVirtual() override {} // 实现纯虚函数
  12. };
  13. int main() {
  14. AbstractBase* obj = new Derived();
  15. delete obj; // 触发 "pure virtual method called"
  16. return 0;
  17. }

3. 解决方法

(1) 避免在析构中调用虚函数

  • 修改基类析构逻辑:确保基类的析构函数不调用任何可能被子类重写为纯虚函数的成员。
  1. class AbstractBase {
  2. public:
  3. virtual ~AbstractBase() {
  4. // 不再调用 pureVirtual()
  5. }
  6. };

(2) 将纯虚函数改为非纯虚并提供默认实现

  1. class AbstractBase {
  2. public:
  3. virtual ~AbstractBase() = default;
  4. virtual void pureVirtual() {} // 非纯虚,提供空实现
  5. };

(3) C++1114+:用 override + final 明确禁止派生类修改关键行为

  1. class AbstractBase {
  2. public:
  3. virtual ~AbstractBase() = default;
  4. virtual void criticalFunction() final { /* ... */ } // 禁止派生类重写
  5. };

4. 多线程场景的额外保护

如果对象可能被多线程访问,需确保析构时没有其他线程正在调用成员函数:

  1. class ThreadSafeDerived : public AbstractBase {
  2. public:
  3. ~ThreadSafeDerived() {
  4. std::lock_guard<std::mutex> lock(mutex_);
  5. // ...析构操作...
  6. }
  7. private:
  8. std::mutex mutex_;
  9. };

5. C++核心准则参考

通过以上方法可以避免该异常。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=23218

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?