现在的位置: 首页 > 综合 > 正文

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

2014年02月12日 ⁄ 综合 ⁄ 共 2212字 ⁄ 字号 评论关闭


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

//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
,因vf
virtual
的。


是的,你已知道这些了。

 

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

void function()

{

 
Sample* p = new
Derived;

 
delete p;

}


既然Sample
没有一个virtual
destructor

,那么delete p
将调用该指针类的dtor
,而不是most derived typde
dtor
Derived::~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.

然后下面就是一个例子,一个class
virtual 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


知道何时让你的dtor
virtual
或者不是取决于人们如何使用你的类。如果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(未定义的)


抱歉!评论已关闭.