【问题标题】:Calling a virtual function from a destructor of a derived class in c++从 C++ 派生类的析构函数调用虚函数
【发布时间】:2020-09-29 16:19:06
【问题描述】:

这是我的 c++ 代码的 sn-p

class A {
public:
    virtual void method() {
        cout << "A::method" << endl;
    }

    virtual ~A() {
        cout << "A::destructor" << endl;
    }

};

class B : public A {
public:
    virtual void method() {
        cout << "B::method" << endl;
    }

    virtual ~B() {
        cout << "B::destructor" << endl;
        method();
    }
};

int _tmain()
{    
    A* a = new B();

    a->method();

    delete a;

    return 0;
}

我了解到,从构造函数或析构函数调用任何虚函数是不可取的。 在派生类 B 的析构函数中,我调用了名为“method()”的虚函数。

这是输出消息。

B::method
B::destructor
B::method
A::destructor

在我看来完全没有问题。虚函数知道它的对象类型并打印 “B::方法()”。这是一种应该避免的未定义行为吗?

【问题讨论】:

  • 不是UB,不是编程错误。这很容易出错,需要格外小心。如果你可以重构你的程序来避免它,那么你未来的错误就会更少,你未来的自己和其他团队成员都会因此而爱上你。
  • 现在,尝试定义class C : public B 覆盖method,看看当你创建和销毁C 类型的对象时会发生什么。
  • @YSC 我刚刚定义了 class C。 class C : public B { public: virtual void method() { cout 方法();删除一个;返回0;并且输出消息在这里: C::method C::destructor C::method B::destructor B::method A::destructor
  • 是的。如果这是您的程序的预期行为,那很好。如果没有,你就有了一个错误并且很难追踪。 demo
  • 感谢您帮助我。我坚信对于未来的自己,应该避免使用构造函数或析构函数中的虚函数。

标签: c++


【解决方案1】:

从概念上讲,B 中的所有虚函数都可以在析构函数体中访问,因此您的代码很好并且定义良好。

但是您的代码非常脆弱:如果有一个 B 的子类覆盖了 method,那将是另一回事。在这种情况下,在 B 的析构函数体中写入 B::method(); 就足够了。

简短回答:最好避免在构造函数和析构函数中调用虚方法。

【讨论】:

    猜你喜欢
    • 2015-04-16
    • 1970-01-01
    • 2011-09-27
    • 2019-04-19
    • 2011-09-08
    • 1970-01-01
    • 2021-05-18
    • 1970-01-01
    • 2013-03-30
    相关资源
    最近更新 更多