《类组合成员初始化课件》由会员分享,可在线阅读,更多相关《类组合成员初始化课件(31页珍藏版)》请在金锄头文库上搜索。
1、 C+ 中,提供了用一个对象值创建并初始化另一个对中,提供了用一个对象值创建并初始化另一个对象的方法,完成该功能的是拷贝构造函数。例如:象的方法,完成该功能的是拷贝构造函数。例如: Tdate d1(2002,3,1); Tdate d2(d1); 用构造函数创建用构造函数创建d1 的值初始化新创建的对象的值初始化新创建的对象d2。拷贝构造函数的特点:拷贝构造函数的特点:1、拷贝构造函数名字与类同名,没有返回类型;、拷贝构造函数名字与类同名,没有返回类型;2、拷贝构造函数只有一个形参数,该参数是该类的对象、拷贝构造函数只有一个形参数,该参数是该类的对象的引用;的引用;拷贝构造函数拷贝构造函数(
2、Copy Constructor)拷贝构 造 函 数13、拷贝构造函数的格式如下:、拷贝构造函数的格式如下: :(&) 其中,其中, 与该类名相同;与该类名相同;例如:下面程序说明了调用拷贝构造函数的过程例如:下面程序说明了调用拷贝构造函数的过程#include class Tpoint public: Tpoint(int xp,int yp) x=xp; y=yp; Tpoint(Tpoint& p); /拷贝构造函数拷贝构造函数拷贝构 造 函 数2 int xcoord() return x; int ycoord() return y; private: int x,y;Tpoint:
3、Tpoint(Tpoint& p) x=p.x; y=p.y; cout“Copy_initialization constructor called.n”;拷贝构 造 函 数3void main() Tpoint p1(5,7); Tpoint p2(p1); cout“p2=”p2.xcoord()“,”p2.ycoord()endl;结果:结果:Copy_initialization constructor called.P2=5,7拷贝构 造 函 数4注意:注意: 如果一个类中没有定义拷贝构造函数,如果一个类中没有定义拷贝构造函数,则系统自动生成一个缺省拷贝构造函数,其则系统自动生成一
4、个缺省拷贝构造函数,其功能是将已知对象的所有数据成员的值拷贝功能是将已知对象的所有数据成员的值拷贝给对应对象的数据成员。给对应对象的数据成员。 class A class A float x, y; float x, y; public:public: A(float a, float b) A(float a, float b) x=a; y=b; cout x=a; y=b; cout调用了构造函数调用了构造函数调用了构造函数调用了构造函数n; n; void Print void Print()()()() coutxtyendl; coutxtyendl; ; ;拷贝构 造 函 数5调
5、用了构造函数调用了构造函数1.02.01.02.01.02.0void main(void) A a1(1.0, 2.0); A a2(a1); A a3 = a1; /可以这样赋值可以这样赋值 a1.Print(); a2.Print(); a3.Print();拷贝构 造 函 数6拷贝构造函数举例拷贝构造函数举例class Point public: Point(int xx=0,int yy=0)X=xx; Y=yy; Point(Point& p); int GetX() return X; int GetY() return Y; private: int X,Y;Point:Poi
6、nt (Point& p) X=p.X; Y=p.Y; cout拷贝构造函数被调用拷贝构造函数被调用endl;拷贝构 造 函 数7拷贝构造函数调用拷贝构造函数调用(1 1)当用类的一个对象去初始化该类的另一当用类的一个对象去初始化该类的另一个对象时系统自动调用拷贝构造函数实现拷个对象时系统自动调用拷贝构造函数实现拷贝赋值。贝赋值。void main(void) Point A(1,2); Point B(A); /拷贝构造函数被调用拷贝构造函数被调用 coutB.GetX()endl;拷贝构 造 函 数8(2 2)若函数的形参为类对象,调用函数时,)若函数的形参为类对象,调用函数时,实参赋值给
7、形参,系统自动调用拷贝构造实参赋值给形参,系统自动调用拷贝构造函数。例如:函数。例如:void fun1(Point p) coutp.GetX()endl; void main() Point A(1,2); fun1(A); /调用拷贝构造函数调用拷贝构造函数 拷贝构 造 函 数9(3 3)当函数的返回值是类对象时,系统自动)当函数的返回值是类对象时,系统自动调用拷贝构造函数。例如:调用拷贝构造函数。例如:Point fun2() Point A(1,2); return A; /调用拷贝构造函数调用拷贝构造函数void main() Point B; B=fun2(); 拷贝构 造 函
8、数10注意:注意: n如果程序员没有为类声明拷贝初始化构造如果程序员没有为类声明拷贝初始化构造函数,则编译器自己生成一个拷贝构造函数。函数,则编译器自己生成一个拷贝构造函数。n这个构造函数执行的功能是:用作为初始这个构造函数执行的功能是:用作为初始值的对象的每个数据成员的值,初始化将要值的对象的每个数据成员的值,初始化将要建立的对象的对应数据成员。建立的对象的对应数据成员。拷贝构 造 函 数11构造函数和析构函数举例构造函数和析构函数举例#includeusing namespace std;class Point public: Point(int xx,int yy); Point();
9、/.其它函数原形其它函数原形 private: int X,int Y;Point:Point(int xx,int yy) X=xx; Y=yy;Point:Point() /.其它函数的实现略其它函数的实现略构 造 函 数 和 析 构 函 数12构造函数和析构函数调用举例构造函数和析构函数调用举例#include using namespace std;class Q int x,y; public: Q(int a=0,int b=0) cout“调用了构造函数调用了构造函数”endl; x=a;y=b; void P(void) coutxtyn; Q() cout“调用了析构函数调用
10、了析构函数!”n;void main(void) Q q(50,100); q.P(); cout“退出主数退出主数!”n”;输出:输出:调用了构造函数调用了构造函数50 10050 100退出主函数!退出主函数!调用了析构函数!调用了析构函数!构 造 函 数 和 析 构 函 数13类的应用举例类的应用举例一圆型游泳池如图所示,现在需在其周围建一一圆型游泳池如图所示,现在需在其周围建一圆型过道,并在其四周围上栅栏。栅栏价格为圆型过道,并在其四周围上栅栏。栅栏价格为35元元/米,过道造价为米,过道造价为20元元/平方米。过道宽度为平方米。过道宽度为3米,游米,游泳池半径由键盘输入。要求编程计算并
11、输出过道和泳池半径由键盘输入。要求编程计算并输出过道和栅栏的造价。栅栏的造价。游泳池过道构 造 函 数 和 析 构 函 数14#include using namespace std;const float PI = 3.14159;const float FencePrice = 35;const float ConcretePrice = 20;class Circle /声明类声明类Circle 及其数据和方法及其数据和方法 private: float radius; public: Circle(float r); /构造函数构造函数 float Circumference(); /
12、圆周长圆周长 float Area() ; /圆面积圆面积;Circle:Circle(float r) /构造函数初始化数据成员构造函数初始化数据成员radiusradius=r; float Circle:Circumference() / 计算圆的周长计算圆的周长 return 2 * PI * radius; float Circle:Area() /计算圆的面积计算圆的面积 return PI * radius * radius;构 造 函 数 和 析 构 函 数15void main () float radius; float FenceCost, ConcreteCost; c
13、outradius; Circle Pool(radius); /声明声明 Circle 对象对象 Circle PoolRim(radius + 3); FenceCost = PoolRim.Circumference() * FencePrice; /计算栅栏造价并输出计算栅栏造价并输出 cout Fencing Cost is ¥ FenceCost endl; ConcreteCost = (PoolRim.Area() -Pool.Area()*ConcretePrice; /计算过道造价并输出计算过道造价并输出 cout Concrete Cost is ¥ ConcreteCo
14、st endl;运行结果运行结果Enter the radius of the pool: 10Enter the radius of the pool: 10Fencing Cost is Fencing Cost is ¥2858.852858.85Concrete Cost is Concrete Cost is ¥4335.34335.3构 造 函 数 和 析 构 函 数16#include “tpoint.h”Tpoint fun(Tpoint q);void main() Tpoint M(12,20),P(0,0),S(0,0); Tpoint N(M); P=fun(N); S
15、=M;cout“P=”P.xcoord()“,”P.ycoord() endl; cout“S=”S.xcoord()“,”S.ycoord() endl;Tpoint fun(Tpoint q) cout“OKn”; int x=q.xcoord()+10; int y=q.ycoord()+15;17 Tpoint R(x,y); return R;/tpoint.h#include class Tpoint public: Tpoint(int xp,int yp) x=xp; y=yp; Tpoint(Tpoint& p); Tpoint() cout“Destructor calle
16、d.n”; int xcoord() return x; int ycoord() return y; private: int x,y;18Tpoint:Tpoint(Tpoint& p) x=p.x; y=p.y; cout“Copy_initialization constructor called.n”;输出结果如下:输出结果如下:Copy_initialization constructor called.Copy_initialization constructor called.OKCopy_initialization constructor called.Destructor
17、 called.Destructor called.Destructor called.19 P=22,35P=22,35 S=12,20 S=12,20 Destructor called. Destructor called. Destructor called. Destructor called. Destructor called. Destructor called. Destructor called. Destructor called.程序输出结果说明程序中出现了三次调用构造函数:程序输出结果说明程序中出现了三次调用构造函数:Tpoint N(M); /M 对象创建对象创建N
18、 对象对象P=fun(N); /实参实参N 对象被拷贝到形参对象被拷贝到形参q对象对象return R; /函数返回时,调用拷贝构造函数,用对象函数返回时,调用拷贝构造函数,用对象R创建创建 / 一个临时对象,保存一个临时对象,保存R 的数据,在主函数中临的数据,在主函数中临 / 时对象被释放前,将它的内容赋值到对象时对象被释放前,将它的内容赋值到对象P 中。中。临时对象临时对象P放放 入入取取 出出Rfun()主函数主函数 暂存区暂存区 main()区区临时对象起暂存作用的情况如下图所示:临时对象起暂存作用的情况如下图所示:20组合的概念组合的概念n类中的成员数据是另一个类的对象。类中的成员
19、数据是另一个类的对象。n可以在已有的抽象的基础上实现更复杂可以在已有的抽象的基础上实现更复杂的抽象。的抽象。 通过对复杂对象进行分解、抽象,使我们能够通过对复杂对象进行分解、抽象,使我们能够将一个复杂对象理解为简单对象的组合;分解将一个复杂对象理解为简单对象的组合;分解得到复杂对象的部件对象,这些部件对象比它得到复杂对象的部件对象,这些部件对象比它高层的复杂对象更容易理解和实现,然后由这高层的复杂对象更容易理解和实现,然后由这些部件对象了些部件对象了“装配装配”复杂对象复杂对象类 的 组 合21例如:例如:#include class Student public: Student() cou
20、t“Constructing student.n”; semeshours=100; gpa=3.5; 22 Student() cout “Destructing student.n”; protected: int semeshours; float gpa;class Teacher public: Teacher() cout“Constructing teacher.n”; 23 Teacher() cout “Destructing teacher.n”; ;class Tutorpair public: Tutorpair() cout“Constructing tutorpai
21、r.n”; nomeetings=0; Tutorpair() cout“Destructing tutorpair.n”; 24 protected: Student student; Teacher teacher; int nomeetings;void main() Tutorpair tp; cout“Back in main.n”;Constructing student.Constructing teacher.Constructing tutorpair.Back in main.Destructing tutorpair.Destructing teacher.Destruc
22、ting student.运行结果:运行结果:25举例举例class Point private: float x,y; /点的坐标点的坐标 public: Point(float h,float v); /构构造函数造函数 float GetX(void); /取取X坐标坐标 float GetY(void); /取取Y坐标坐标 void Draw(void); /在在(x,y)处画点处画点;/.函数的实现略函数的实现略class Line private: /线段的两个端点线段的两个端点 Point p1,p2; public: /构造函数构造函数 Line(Point a,Point b
23、); /画出线段画出线段 Void Draw(void);/.函数的实现略函数的实现略类 的 组 合26类组合的构造函数设计类组合的构造函数设计n原则:不仅要负责对本类中的基本类型成原则:不仅要负责对本类中的基本类型成员数据赋初值,也要对对象成员初始化。员数据赋初值,也要对对象成员初始化。n声明形式:声明形式:类名类名:类名类名(对象成员所需的形参,本类成员形对象成员所需的形参,本类成员形参参) :对象:对象1(参数参数),对象,对象2(参数参数),. 本类初始化本类初始化 类 的 组 合27类组合构造函数实例类组合构造函数实例Point(int xx=0,int yy=0) x=xx;y=y
24、y;Line:Line(Point a,Point b,double p):p1(a),p2(b) double x=double(p1.GetX()-p2.GetX(); double y=double(p1.GetY()-p2.GetY(); dist=sqrt(x*x+y*y); price=p; 类 的 组 合28类组合的构造函数调用类组合的构造函数调用n构造函数调用顺序:先调用内嵌对象的构构造函数调用顺序:先调用内嵌对象的构造函数(按内嵌时的声明顺序,先声明者造函数(按内嵌时的声明顺序,先声明者先构造)。然后调用本类的构造函数。先构造)。然后调用本类的构造函数。(析构函数的调用顺序相
25、反)(析构函数的调用顺序相反)n若调用默认构造函数(即无形参的),则若调用默认构造函数(即无形参的),则内嵌对象的初始化也将调用相应的默认构内嵌对象的初始化也将调用相应的默认构造函数。造函数。类 的 组 合29类的组合举例类的组合举例1#include #include using namespace std;class Point private: float x,y; /点的坐标点的坐标 public: Point(float xx,float yy) cout“Point构造函数构造函数”endl; x=xx;y=yy; Point(Point &p) x=p.x;y=p.y; cout
26、“Point拷贝构造函数拷贝构造函数”endl; float GetX(void)return x; float GetY(void)return y;类 的 组 合30class Distance private: Point p1,p2; /线段的两个端点线段的两个端点 double dist; public: Distance(Point a,Point b); /构造函数构造函数 double GetDis(void)return dist;Distance:Distance(Point a,Point b):p1(a),p2(b) cout“Distance构造函数构造函数”endl; double x=double(p1.GetX()-p2.GetX(); double y=double(p1.GetY()-p2.GetY(); dist=sqrt(x*x-y*y); void main() Point myp1(1,1),myp2(4,5); Distance myd(myp1,myp2); cout“the distance is:”; coutmyd.GetDis()endl;类 的 组 合31