开发环境:GNU GCC(g ++)4.1.2
虽然我试图研究如何在单元测试中增加'代码覆盖率-尤其是功能覆盖率,但我发现某些类dtor似乎多次生成。你们当中有人对为什么有任何想法吗?
我尝试并通过使用以下代码观察了上面提到的内容。
在“ test.h”中
class BaseClass
{
public:
~BaseClass();
void someMethod();
};
class DerivedClass : public BaseClass
{
public:
virtual ~DerivedClass();
virtual void someMethod();
};
在“ test.cpp”中
#include <iostream>
#include "test.h"
BaseClass::~BaseClass()
{
std::cout << "BaseClass dtor invoked" << std::endl;
}
void BaseClass::someMethod()
{
std::cout << "Base class method" << std::endl;
}
DerivedClass::~DerivedClass()
{
std::cout << "DerivedClass dtor invoked" << std::endl;
}
void DerivedClass::someMethod()
{
std::cout << "Derived class method" << std::endl;
}
int main()
{
BaseClass* b_ptr = new BaseClass;
b_ptr->someMethod();
delete b_ptr;
}
当我构建上面的代码(g ++ test.cpp -o测试),然后查看生成了以下哪种类型的符号时,
nm-脱胶测试
我可以看到以下输出。
==== following is partial output ====
08048816 T DerivedClass::someMethod()
08048922 T DerivedClass::~DerivedClass()
080489aa T DerivedClass::~DerivedClass()
08048a32 T DerivedClass::~DerivedClass()
08048842 T BaseClass::someMethod()
0804886e T BaseClass::~BaseClass()
080488f6 T BaseClass::~BaseClass()
我的问题如下。
1)为什么生成了多个dtor(BaseClass-2,DerivedClass-3)?
2)这些dtor之间有什么区别?如何选择使用这些多个dtor?
我现在感觉,为了实现C ++项目的100%功能覆盖,我们需要理解这一点,以便我可以在单元测试中调用所有这些dtor。
如果有人能给我以上的答复,我将不胜感激。
首先,这些功能的目的在Itanium C++ ABI中进行了说明;请参见“基础对象析构函数”,“完整对象析构函数”和“删除析构函数”下的定义。在5.1.4中给出了到错误名称的映射。
基本:
operator delete
来实际释放内存。如果没有虚拟基类,则D2和D1相同;在足够的优化级别上,GCC实际上会将符号的别名别名化为相同的代码。
通常有构造函数的两个变体(in-in-charge / in-charge)和三个析构函数(not-in-charge / in-charge / 负责删除)。
当对象不是完整对象(因此当前对象是完整对象)时,使用not-in-charge ctor和dtor来处理使用virtual
关键字从另一个类继承的类的对象。 “不负责”构建或销毁虚拟基础对象)。此ctor接收指向虚拟基础对象的指针并将其存储。
in-charge ctor和dtor用于所有其他情况,即,不涉及虚拟继承;如果该类具有虚拟析构函数,则in-charge delete dtor指针将进入vtable插槽,而知道对象动态类型(例如,具有自动或静态存储持续时间的对象)的范围将使用负责 dtor(因为不应释放此内存)。
代码示例:
struct foo { foo(int); virtual ~foo(void); int bar; }; struct baz : virtual foo { baz(void); virtual ~baz(void); }; struct quux : baz { quux(void); virtual ~quux(void); }; foo::foo(int i) { bar = i; } foo::~foo(void) { return; } baz::baz(void) : foo(1) { return; } baz::~baz(void) { return; } quux::quux(void) : foo(2), baz() { return; } quux::~quux(void) { return; } baz b1; std::auto_ptr<foo> b2(new baz); quux q1; std::auto_ptr<foo> q2(new quux);
结果:
foo
和baz
的每个vtable中的dtor条目指向相应的in-charge删除 dtor。quux
和b1
由b2
in-chargebaz()
in-chargefoo(1)
和q1
由q2
in-chargequux()
in-charge和foo(2)
not-in-charge落在指向它先前构建的baz()
对象的指针foo
被q2
in-charge~auto_ptr()
in-charge delete,将其称为~quux()
not-in-charge ,~baz()
主管和~foo()
。operator delete
被q1
in-charge~quux()
not-in-charge和~baz()
in-charge~foo()
被b2
in-charge~auto_ptr()
in-charge delete,后者将~baz()
in-charge和[ C0]~foo()
被operator delete
in-chargeb1
in-charge从~baz()
派生的任何人都将使用其非负责人
~foo()
对象。原则上,对于没有虚拟基础的类,永远不需要not-in-charge
变体;在那种情况下,in-charge变体有时称为unified,和/或in-charge和not-in-charge的符号都别名为单个实现。