Mar*_*ark 151 c++ destructor pure-virtual
我理解虚拟析构函数的必要性.但为什么我们需要纯虚拟析构函数?在其中一篇C++文章中,作者提到我们在创建类抽象时使用纯虚析构函数.
但是我们可以通过将任何成员函数设置为纯虚拟来使类抽象化.
所以我的问题是
我们什么时候才能真正使析构函数变为虚拟?任何人都能给出一个很好的实时例子吗?
当我们创建抽象类时,将析构函数设置为纯虚拟是一种很好的做法吗?如果是..那为什么?
Mot*_*tti 115
允许纯虚拟析构函数的真正原因可能是禁止它们意味着在语言中添加另一条规则,并且不需要这条规则,因为允许纯虚拟析构函数不会产生任何不良影响.
不,简单的老虚拟就足够了.
如果使用其虚拟方法的默认实现创建一个对象,并希望在不强制任何人覆盖任何特定方法的情况下使其成为抽象,则可以使析构函数为纯虚拟.我没有看到太多的意义,但它是可能的.
请注意,由于编译器将为派生类生成隐式析构函数,如果类的作者不这样做,则任何派生类都不是抽象的.因此,在基类中使用纯虚析构函数不会对派生类产生任何影响.它只会使基类抽象(感谢@kappa的评论).
也可以假设每个派生类可能需要具有特定的清理代码并使用纯虚拟析构函数作为提示来编写一个,但这似乎是人为的(并且是非强制的).
注意:析构函数是唯一的方法,即使它是纯虚拟的,也必须有一个实现来实例化派生类(是的纯虚函数可以有实现).
struct foo {
virtual void bar() = 0;
};
void foo::bar() { /* default implementation */ }
class foof : public foo {
void bar() { foo::bar(); } // have to explicitly call default implementation.
};
Run Code Online (Sandbox Code Playgroud)
Bra*_*den 32
抽象类所需要的只是至少一个纯虚函数.任何功能都可以; 但是当它发生时,析构函数是任何类都会有的 - 所以它总是作为候选者存在.此外,使析构函数纯虚拟(而不仅仅是虚拟)除了使类抽象之外没有任何行为副作用.因此,许多样式指南建议始终使用纯虚拟目标来指示一个类是抽象的 - 如果没有其他原因,它提供一致的位置,有人阅读代码可以查看该类是否是抽象的.
lea*_*der 18
如果要创建抽象基类:
...通过使析构函数为纯虚拟并为其提供定义(方法体),最简单的方法是使类抽象化.
对于我们假设的ABC:
您保证它不能被实例化(即使是类本身内部,这就是私有构造函数可能不够的原因),您获得了析构函数所需的虚拟行为,并且您不必查找并标记另一个方法不需要虚拟调度作为"虚拟".
从我读到的答案到你的问题,我无法推断出一个真正使用纯虚析构函数的理由.例如,以下原因并不能说服我:
允许纯虚拟析构函数的真正原因可能是禁止它们意味着在语言中添加另一条规则,并且不需要这条规则,因为允许纯虚拟析构函数不会产生任何不良影响.
在我看来,纯虚拟析构函数可能很有用.例如,假设代码中有两个类myClassA和myClassB,myClassB继承自myClassA.由于Scott Meyers在他的"更有效的C++"一书中提到的原因,第33项"使非叶类抽象化",实际上创建一个myClassA和myClassB继承的抽象类myAbstractClass是更好的做法.这提供了更好的抽象并防止了例如对象副本引起的一些问题.
在抽象过程(创建类myAbstractClass)中,可能没有myClassA或myClassB的方法是一个很好的候选者,因为它是一个纯虚方法(这是myAbstractClass抽象的先决条件).在这种情况下,您可以定义抽象类的析构函数pure virtual.
以下是我自己写的一些代码的具体例子.我有两个类,Numerics/PhysicsParams,它们共享共同的属性.因此,我让他们继承自抽象类IParams.在这种情况下,我绝对没有可以纯粹是虚拟的方法.例如,setParameter方法必须为每个子类具有相同的主体.我唯一的选择是让IParams的析构函数纯粹是虚拟的.
struct IParams
{
IParams(const ModelConfiguration& aModelConf);
virtual ~IParams() = 0;
void setParameter(const N_Configuration::Parameter& aParam);
std::map<std::string, std::string> m_Parameters;
};
struct NumericsParams : IParams
{
NumericsParams(const ModelConfiguration& aNumericsConf);
virtual ~NumericsParams();
double dt() const;
double ti() const;
double tf() const;
};
struct PhysicsParams : IParams
{
PhysicsParams(const N_Configuration::ModelConfiguration& aPhysicsConf);
virtual ~PhysicsParams();
double g() const;
double rho_i() const;
double rho_w() const;
};
Run Code Online (Sandbox Code Playgroud)
这里我想告诉我们什么时候需要虚析构函数,什么时候需要纯虚析构函数
class Base
{
public:
Base();
virtual ~Base() = 0; // Pure virtual, now no one can create the Base Object directly
};
Base::Base() { cout << "Base Constructor" << endl; }
Base::~Base() { cout << "Base Destructor" << endl; }
class Derived : public Base
{
public:
Derived();
~Derived();
};
Derived::Derived() { cout << "Derived Constructor" << endl; }
Derived::~Derived() { cout << "Derived Destructor" << endl; }
int _tmain(int argc, _TCHAR* argv[])
{
Base* pBase = new Derived();
delete pBase;
Base* pBase2 = new Base(); // Error 1 error C2259: 'Base' : cannot instantiate abstract class
}
Run Code Online (Sandbox Code Playgroud)
当您希望没有人能够直接创建 Base 类的对象时,请使用纯虚拟析构函数virtual ~Base() = 0
。通常至少需要一个纯虚函数,让我们把 virtual ~Base() = 0
, 作为这个函数。
当你不需要上面的东西时,你只需要派生类对象的安全销毁
Base* pBase = new Derived(); 删除 pBase;不需要纯虚拟析构函数,只有虚拟析构函数才能完成这项工作。
归档时间: |
|
查看次数: |
82059 次 |
最近记录: |