• 什么时候你需要一个虚构函数是虚的


    什么时候你需要一个虚构函数是虚的?
    //z 2011-06-10 22:58:36@is2120.CSDN
    转载请注明出处
    tag: virtual destructor dtor
    虚构函数 虚虚构函数 虚函数
    你的c++ 对象的虚构函数何时应为virtual

    首先,拥有一个虚虚函数意味着什么?

    嗯,拥有一个虚函数意味着什么?

    如果一个 函数是虚函数,那么在一个object 上调用一个函数总是调用由the most heavily derived class 实现的method 。如果method 不是virtual ,那么实现就对应到对象指针编译时的类型。

    举例如下:
    For example, consider this:

    class Sample {

    public:

      void f();

      virtual void vf();

    };

     

    class Derived : public Sample {

    public:

      void f();

      void vf();

    }

     

    void function()

    {

      Derived d;

      Sample* p = &d;

      p->f();

      p->vf();

    }

    p->f() 调用将导致调用Sample::f ,因p 是一个指向Sample 的指针。真实object 是派生的类型,但是指针仅仅是一个指向Sample 的指针。这里使用了指针类型(相对实际的object type ),因f 不是virtual 的。
    //z 2011-06-10 22:58:36@is2120.CSDN 转载请注明出处

    另一方面,p->vf() 调用将导致一个Derived::vf 的调用,the most heavily derived type ,因vfvirtual 的。


    是的,你已知道这些了。

     

    Virtual destructors 完全同样的工作方式。只是你很少显式调用dtor 。更确切地说,当一个自动变量出其scope 时或者你删除(new,delete )一个对象时就会调用dtor

    void function()

    {

      Sample* p = new Derived;

      delete p;

    }


    既然Sample 没有一个virtual destructor ,那么delete p 将调用该指针类的dtor ,而不是most derived typdedtorDerived::~Derived() )。如你所见,在上述情景中这是不正确的事情。

    有了这些信息在手,你就可以回答开头的问题了。

     

    如果你一个类满足了下面两个条件,那么必须有一个virtual destructor

     

    . 你会delete p
    .p
    实际会指向一个派生类

    一些人认为你需要一个virtual dtor 当且仅当你有一个virtual method 。这在双向上都是不正确的。

    下面就是没有virtual method 但是仍旧需要 virtual dtor 的例子:
    class Sample { };

    class Derived : public Sample

    {

      CComPtr<IStream> m_p;

    public:

      Derived() { CreateStreamOnHGlobal(NULL, TRUE, &m_p); }

    };

     

    Sample *p = new Derived;

    delete p;

    delete p 将导致调用 Sample::~Sample 而不是Derived::~Derived 。这将导致stream m_p 的一个泄漏。
    The delete p will invoke Sample::~Sample instead of Derived::~Derived, resulting in a leak of the stream m_p.

    然后下面就是一个例子,一个classvirtual method 但是不需要一个virtual dtor
    class Sample { public: virtual void vf(); }

    class Derived : public Sample { public: virtual void vf(); }

     

    Derived *p = new Derived;

    delete p;

    既然指针类型和对象类型一致,那么相应正确的dtor 就会别调用。这个模式在com 对象中经常如此,这些对象常常根据对应的接口输出几个virtual methods ,但是对象本身由其自身的实现来销毁而不是从一个基类指针(注意没有com 接口包含一个虚拟dtor
    知道何时让你的dtorvirtual 或者不是取决于人们如何使用你的类。如果c++ 有一个“sealed ”关键字,那么规则就会简单多了:如果在一个非sealed class 上调用“delete p ”,那么class 需要有一个virtual dtor

    『虚幻的 sealed 关键字使得它是显式的,当一个类能够作为另一个类的基类』
    //z 2011-06-10 22:58:36@is2120.CSDN 转载请注明出处



    补充材料:

    class A{
    public:
    A(){}
    ~A(){}
    }

    class B{
    B(){}
    ~B(){}
    }

    A * a = new B;

    delete a;

    在标准中有有关规格说明如下( 5.3.5 /3 ):

    if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined.

     

    从而如上的情况是UB(未定义的)

  • 相关阅读:
    Win7 安装 IIS 7.5 及部署 .NET 程序到 IIS 的内容杂记
    乐嘉,你快回来
    AMD将要嫁他人?
    高精度运算(运算符重载)
    魔数卡牌
    C语言"#","#@"和"##"在宏定义中的使用技巧
    CentOS7下安装FTP服务
    Linux下FTP的安装和登陆
    怎么让FOXMAIL关了以后在右下角自动收取邮件
    在CentOS7上安装ftp服务器用于保存服务端上传的图片。
  • 原文地址:https://www.cnblogs.com/IS2120/p/6746036.html
Copyright © 2020-2023  润新知