【问题标题】:Why virtual destructor?为什么是虚拟析构函数?
【发布时间】:2015-11-12 16:56:18
【问题描述】:

我正在浏览一些代码,计划对其进行调整以用于我的研究。所以头文件看起来像这样

#ifndef SPECTRALCLUSTERING_H_
#define SPECTRALCLUSTERING_H_

#include <vector>
#include <eigen3/Eigen/Core>

class SpectralClustering {
public:
    SpectralClustering(Eigen::MatrixXd& data, int numDims);
    virtual ~SpectralClustering();

    std::vector<std::vector<int> > clusterRotate();
    std::vector<std::vector<int> > clusterKmeans(int numClusters);
    int getNumClusters();

protected:
    int mNumDims;
    Eigen::MatrixXd mEigenVectors;
    int mNumClusters;
};

#endif /* SPECTRALCLUSTERING_H_ */

主代码后面

#include "SpectralClustering.h"
#include <eigen3/Eigen/QR>

SpectralClustering::SpectralClustering(Eigen::MatrixXd& data, int numDims):
    mNumDims(numDims),
    mNumClusters(0)

所以我不明白为什么在 .h 文件中使用了虚拟析构函数。从this我们可以了解到,当您可以通过指向基类的指针删除派生类的实例时,虚拟析构函数很有用。但我认为这段代码并非如此。有人能解释一下吗?

【问题讨论】:

  • 如果他们特意定义了一个虚拟析构函数,那是因为他们预计有人会使用SpectralClustering 作为基类来创建派生类。

标签: c++ inheritance virtual-destructor


【解决方案1】:

您将析构函数设为虚拟的原因是您计划将该类继承并以多态方式使用。如果我们有

class Foo {};
class Bar : public Foo {};

Foo * f = new Bar();
delete f; // f's destructor is called here

Foo 的析构函数将被调用,并且对象的 Bar 部分的任何成员都不会被销毁。如果Foo 有一个虚拟析构函数,那么会发生vtable 查找,而Bar 析构函数将被调用,而不是正确地销毁对象。

【讨论】:

    【解决方案2】:

    假设类可以被继承。否则应使用说明符final 声明。

    考虑到类的数据成员具有访问控制说明符protected。意思是类的作者不排除类可以被继承。

    【讨论】:

      【解决方案3】:

      代码可能是这样编写的,即支持通过派生自定义类来自定义类实现。

      框架的用户可以通过这种方式自定义框架,而无需直接更改框架代码。因此,可能有一种方法可以使用您的派生类来代替原始的SpectralClustering 类,或者甚至代替任何派生自SpectralClustering 的类(在这种情况下不是,因为它不是从任何东西派生的)。框架很可能会使用基类引用删除实例,而实际实现是派生的。

      【讨论】:

        猜你喜欢
        • 2011-10-29
        • 2011-09-30
        • 2021-07-17
        • 2012-03-09
        • 2011-02-04
        • 2014-02-12
        • 2010-12-11
        • 1970-01-01
        • 2012-11-03
        相关资源
        最近更新 更多