什么时候你需要一个虚构函数是虚的
2011-06-10 23:04
176 查看
什么时候你需要一个虚构函数是虚的?
//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
转载请注明出处
补充材料:
[/code]
在标准中有有关规格说明如下(
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(未定义的)
//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;
[/code]
在标准中有有关规格说明如下(
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(未定义的)
相关文章推荐
- t-sql判断一个字符串是否为bigint的函数(全角数字需要判断为不合格)
- C函数只能有一个返回值,如果需要返回多个值,怎么办,其实很简单,只要将指针作为函数参数传递就可以了
- php编程时,什么时候需要封装函数,什么时候需要封装类
- [CodeComplete]创建一个函数需要理由吗
- 以Point为基类,派生出一个Circle(圆)类,增加数据成员r(半径),以及求面积的成员函数area,实现其他需要的成员函数,设计main函数完成测试
- 创建一个CPoint类,代表平面直角坐标系中的点,创建构造函数和运算符重载函数, 运算符重载为类重载(非友元重载),可以实现计算两个点之间的距离。可以根据需要 加入自己的成员变量或成员函数
- 如何用javascript 的eval动态执行一个需要传对象参数的函数
- 什么时候需要删除由函数返回的指针
- C++什么时候析构函数需要声明为虚函数
- 写正确函数需要注意的地方:给定一个十进制整数N,计算从1开始到N的所有整数出现的“1”的个数
- 实现一个函数,对一个正整数n,算得到1需要的最少操作次数?
- 函数在什么时候需要“引用”类型的参数
- 在vc中调用一般的.exe只需要一个函数
- 实现一个函数,对一个正整数n,算得到1需要的最少操作次数?
- wpf 透明效果 需要DwmApi.dll文件,然后定义一个函数去画Aero区域,从而实现整个窗口的Aero化。
- 调试使用了函数模块的程序时需要注意的一个小问题
- CreateIpForwardEntry函数在VIsta/win2008下需要注意的一个地方
- 为什么每个C程序都需要一个叫做main的函数
- 调试使用了函数模块的程序时需要注意的一个小问题
- 写正确函数需要注意的地方:输入一个字符串,打印出该字符串中字符的所有排列