//:C11:Combined.cpp
// Inheritance & composition
#include<iostream>
using namespace std;
class A {
int i;
public:
A (int ii) : i(ii) {cout << "run A()"<<'
';}
~A () {cout<< "run ~A()"<<'
';}
void f() const {}
};
class B {
int i;
public:
B(int ii) : i(ii) {cout<<"run B()"<<'
';}
~B (){cout<<"run ~B()"<<'
';}
void f() const {}
};
class C : public B {
A a;
public:
C(int ii) : B(ii),a(ii) {cout<<"run C()"<<'
';}
~C() {cout<<"run ~C()"<<'
';}//calls ~A() and ~B()
void f() const {//Redefinition
a.f();
B::f();
}
};
int main(){
C c(47);
}
C对B进行了继承并且有一个类型A的成员对象(“由类型A的成员对象组合而成”)。 可以看到,构造函数的初始化表达式表中调用了基类构造函数和成员对象构造函数。 函数C:f()重定义了它所继承的B:f(),但同时还调用基类版本。另外,它还调 用了a.f()。注意,只有通过继承,才能重新定义它的函数。而对于成员对象,只能操 作这个对象的公共接口,而不能重定义它。另外,如果C:f()还没有被定义,则对类型 C的一个对象调用f()就不会调用a.f(),而会调用B:f()。 自动析构函数调用 虽然常常需要在初始化表达式表中做显式构造函数调用,但并不需要做显式的析构函 数调用,因为对于任何类型只有一个析构函数,并且它并不取任何参数。然而,编译器仍 要保证所有的析构函数被调用,这意味着,在整个层次中的所有析构函数中,从派生最底 层的析构函数开始调用,一直到根层。 值得强调的是,在每一层中构造函数和析构函数都被调用的情况相当罕见。然而对于 通常的成员函数,只是这个函数被调用,而它的那些基类版本并不会被调用。如果还想调 用重载过的成员函数的基类版本,则必须显式地去做。