第13讲派生类的构造函数与析构函数 教学目的与要求: 了解派生类对象创建和释放的过程。 掌握派生类的构造函数和析构函数的构造规则。 教学内容提要: 1、派生类的构造函数和析构函数的执行顺序; 2、派生类的构造函数和析构函数的构造规则; 3、调整基类成员在派生类中的访问属性 °教学重点:派生类的构造函数和析构函数的构造规则。 教学难点:派生类的构造函数和析构函数的构造规则 教学进度:P123P136 教学过程
•教学目的与要求: 了解派生类对象创建和释放的过程。 掌握派生类的构造函数和析构函数的构造规则。 •教学内容提要: 1、派生类的构造函数和析构函数的执行顺序; 2、派生类的构造函数和析构函数的构造规则; 3、调整基类成员在派生类中的访问属性 •教学重点:派生类的构造函数和析构函数的构造规则。 •教学难点:派生类的构造函数和析构函数的构造规则。 •教学进度:P123~P136 •教学过程: 第 13 讲 派生类的构造函数与析构函数
(131派生类构造函数和析构函数的执行顺序】 对于派生类,由于其中包含有从基类继承来的和派生类中新声 明的数据成员,而派生类和它的基类都有相应的构造函数和析 构函数。 通常情况下: 当创建派生类对象时,首先执行基类的构造函数随后再 执行派生类的构造函数 当撤消派生类对象时,则先执行派生类的析构函数随后 再执行基类的析构函数
对于派生类,由于其中包含有从基类继承来的和派生类中新声 明的数据成员,而派生类和它的基类都有相应的构造函数和析 构函数。 【13.1派生类构造函数和析构函数的执行顺序】 通常情况下: 当创建派生类对象时,首先执行基类的构造函数,随后再 执行派生类的构造函数; 当撤消派生类对象时,则先执行派生类的析构函数,随后 再执行基类的析构函数
例13.1基类和派生类的构造函数及析构函数的执行顺序 #include class baset public: Baseoi cout<< Constructing base classin";5 基类的构造函数 cBaseoi cout<< Destructing baes classIn";j 类的析构函数 class Derive: public Baset public Deriveoicout<< Constructing derived classin") 派生类的构造函数 Derive icout<< Destructing derived classin"; 派生类的析构函数 main Derive op; return 0;1
例13.1 基类和派生类的构造函数及析构函数的执行顺序。 #include class Base{ public: Base(){ cout<<"Constructing base class\n"; } //基类的构造函数 ~Base(){ cout<<"Destructing baes class\n"; } //基类的析构函数 }; class Derive:public Base{ public: Derive(){cout<<"Constructing derived class\n";} //派生类的构造函数 ~Derive(){cout<<"Destructing derived class\n";} //派生类的析构函数 }; main() { Derive op; return 0; }
例132(调用构造函数和析构函数 #includesiostream.h> class B: publica class A public: B0; public: ~B(0; A0; void setz(int cREC, A0; int getztreturn z; void setx(int a)x=a int getsum (return x+gety0+z; void sety(int b)y=b; 3 private int getxO constreturn x; int int geto constreturn y;) protected: A:AO:x(1)2y(2) int x; private: cout<<“调用类A的构造函数” int y: dl
class B:public A { public: B(); ~B(); void setz(int c){z=c;} int getz(){return z;} int getsum(){return x+gety()+z;} private: int z; }; A::A():x(1),y(2) { cout class A { public: A(); ~A(); void setx(int a){x=a;} void sety(int b){y=b;} int getx() const{return x;} int gety() const{return y;} protected: int x; private: int y; }; 例 13.2 调用构造函数和析构函数
(续) cout<"调用类A的析构函数”<<endl; B:B0:z(3) cout<"调用类B的构造函数<<endl; B:~B0 cout<<"调用类B的析构函数<<end; void maino Bb cout<<x=<<bgetx(<<tY="<<b. getyo ItzA<<b. getz(<<endl cout<<"x+Y+z=<<b getsum(<<endl;
A:: ~A() { cout<<″调用类 A的析构函数″<<endl; } B::B():z(3) { cout<<″调用类 B的构造函数″<<endl; } B:: ~B() { cout<<″调用类 B的析构函数″<<endl; } void main() { B b; cout<<″X=″<<b.getx()<<″ \tY=″<<b.gety() <<″ \tZ=″<<b.getz()<<endl; cout<<″X+Y+Z=″<<b.getsum()<<endl; } (续)
(续) 调用类A的构造函数 调用类B的构造函数 Y=2 Z=3 X+Y+7=6 调用类B的析构函数 调用类A的析构函数 注 在创建派生类的对象时,系统将首先调用其基类的构造 函数来初始化从基类中继承的数据成员,然后调用派生类自身 的构造函数初始化在派生类中新声明的数据成员。终止对象时, 析构函数的执行顺序则正好相反,即先调用派生类的析构函数 清除派生类中新声明的数据成员,再调用基类的析构函数清除 从基类中继承的数据成员
在创建派生类的对象时,系统将首先调用其基类的构造 函数来初始化从基类中继承的数据成员,然后调用派生类自身 的构造函数初始化在派生类中新声明的数据成员。终止对象时, 析构函数的执行顺序则正好相反,即先调用派生类的析构函数 清除派生类中新声明的数据成员,再调用基类的析构函数清除 从基类中继承的数据成员。 注 调用类A的构造函数 调用类B的构造函数 X=1 Y=2 Z=3 X+Y+Z=6 调用类B的析构函数 调用类A的析构函数 (续)
(132派生类构造函数和析构函数的构造规则】 通过为派生类定义一个带有初始化列表的构造函数 在C++中,派生类构造函数的一般格式为 派生类名(参数总表)基类名(参数表) ∥派生类新增成员的初始化语句
1、在C++中,派生类构造函数的一般格式为: 派生类名(参数总表):基类名(参数表) { // 派生类新增成员的初始化语句 }; 通过为派生类定义一个带有初始化列表的构造函数。 【13.2派生类构造函数和析构函数的构造规则】
例133当基类含有带参数的构造函数时,派生类构造函数的构造方 法 #includesiostream.h> class base i public: Base(int n) ∥基类的构造函数 cout<< Constructing base classIn" In, Basel 类的析构函数 i cout<< Destructing base classIn";) void shown cout<<i<<endl; private: int i
例13.3 当基类含有带参数的构造函数时, 派生类构造函数的构造方 法。 #include class Base { public: Base(int n) //基类的构造函数 { cout<<"Constructing base class\n"; i=n; } ~Base() //基类的析构函数 { cout<<"Destructing base class\n"; } void showi() { cout<<i<<endl; } private: int i; };
class Derive public Base public: Derive(intn,intm)Base(m)∥定义派生类构造函数时, ∥缀上基类的构造函数 cout<< Constructing derived class"<<endl; j=n;) Derive 派生类的析构函数 i cout<<"Destructing derived class"<<endl; void showjOf cout<<j<<endl; s private: int maino Derive obj(50, 60) obj. showi0; obj. showjO return O
class Derive :public Base{ public: Derive(int n,int m):Base(m) // 定义派生类构造函数时, { // 缀上基类的构造函数 cout<<"Constructing derived class"<<endl; j=n; } ~Derive() //派生类的析构函数 { cout<<"Destructing derived class"<<endl; } void showj(){ cout<<j<<endl;} private: int j; }; main() { Derive obj(50,60); obj.showi(); obj.showj(); return 0; }
2、当派生类中含有内嵌对象成员时,其构造函数的一般形式为: 参数总表应包括初始化基类数据成员、内嵌对象数 据成员及其他数据成员所需的全部数据。 派生类名::派生类名(参数总表):基类(参数表),对象成 员1(对象成员参数表1),对象成员2(对象成员参数表2),…, 对象成员n(对象成员参数表n) 派生类中新声明的数据成员初始化语句 是需要用参数初始化的基类名、对象成员名及各自对应的参数表 基类名和对象成员名之间的顺序可以是任意的,且对于使用默认 构造函数的基类和对象成员,可以不列出基类名和对象成员名。 对象成员是指在派生类中新声明的数据成员,它是属于另外一个 类的对象。对象成员必须在初始化列表中初始化
派生类名::派生类名(参数总表):基类(参数表),对象成 员1(对象成员参数表1),对象成员2(对象成员参数表2),…, 对象成员n(对象成员参数表n) { 派生类中新声明的数据成员初始化语句 } 参数总表应包括初始化基类数据成员、内嵌对象数 据成员及其他数据成员所需的全部数据。 是需要用参数初始化的基类名、对象成员名及各自对应的参数表, 基类名和对象成员名之间的顺序可以是任意的,且对于使用默认 构造函数的基类和对象成员,可以不列出基类名和对象成员名。 对象成员是指在派生类中新声明的数据成员,它是属于另外一个 类的对象。对象成员必须在初始化列表中初始化。 2、当派生类中含有内嵌对象成员时,其构造函数的一般形式为: