struct A {};
struct B : A { B() : A() {} };
// but this works as well because compiler inserts call to A():
struct B : A { B() {} };
// however this does not compile:
struct A { A(int x) {} };
struct B : A { B() {} };
// you need:
struct B : A { B() : A(4) {} };
7 回答
标准说
此外,根据RAII资源需要与适当对象的生命周期相关联,并且必须调用各个类的析构函数来释放资源 .
例如,以下代码泄漏内存 .
Constructor and destructor are different from the rest of regular methods.
Constructor
不能是虚拟的
在派生类中,您要么显式调用基类的构造函数
或者,如果你没有调用基类构造函数编译器将插入调用 . 它将调用不带参数的基础构造函数 . 如果不存在这样的构造函数,则会出现编译器错误 .
Destructor :
输出:
如果基类中的方法被标记为
virtual
,则所有继承的方法都是虚拟的,所以即使你没有将D
和E
中的析构函数标记为virtual
,它们仍然是virtual
,它们仍然以相同的顺序被调用 .这是设计的 . 必须调用基类上的析构函数才能释放其资源 . 经验法则是派生类应该只清理自己的资源并让基类自行清理 .
从C++ spec:
此外,因为只有一个析构函数,所以类必须调用哪个析构函数没有歧义 . 构造函数不是这种情况,如果没有可访问的默认构造函数,程序员必须选择应该调用哪个基类构造函数 .
因为这就是dtor的工作方式 . 当你创建一个对象时,从基数开始调用ctors,并一直到最大的派生 . 当您(正确地)销毁对象时,会发生相反的情况 . 使dtor虚拟产生差异的时间是,是否/当你通过指针(或引用,虽然这是相当不寻常的)对基类型销毁对象时 . 在那种情况下,替代方案并不是真的只有派生的dtor被调用 - 相反,替代方案只是未定义的行为 . 这种情况恰好采用仅调用派生的dtor的形式,但它也可能采用完全不同的形式 .
正如Igor所说,必须为基类调用构造函数 . 考虑如果不调用会发生什么:
如果在删除
B
实例时不会调用A
的析构函数,则永远不会清除A
.基类析构函数可能负责清理由基类构造函数分配的资源 .
如果您的基类有一个默认构造函数(一个不带参数或者它的所有参数都有默认值),那么在构造派生实例时会自动调用构造函数 .
如果您的基类具有需要参数的构造函数,则必须在派生类构造函数的初始化列表中手动调用它 .
由于析构函数不接受参数,因此在删除派生实例时将始终自动调用基类析构函数 .
如果您正在使用多态并且您的派生实例由基类指针指向,那么只有在基本析构函数为虚拟时才会调用 derived 类析构函数 .
当任何对象被销毁时,析构函数将针对所有子对象运行 . 这包括通过包含重用和通过继承重用 .