一面向对象程序设计方案理论.ppt

上传人:sccc 文档编号:5663822 上传时间:2023-08-07 格式:PPT 页数:80 大小:300.54KB
返回 下载 相关 举报
一面向对象程序设计方案理论.ppt_第1页
第1页 / 共80页
一面向对象程序设计方案理论.ppt_第2页
第2页 / 共80页
一面向对象程序设计方案理论.ppt_第3页
第3页 / 共80页
一面向对象程序设计方案理论.ppt_第4页
第4页 / 共80页
一面向对象程序设计方案理论.ppt_第5页
第5页 / 共80页
点击查看更多>>
资源描述

《一面向对象程序设计方案理论.ppt》由会员分享,可在线阅读,更多相关《一面向对象程序设计方案理论.ppt(80页珍藏版)》请在三一办公上搜索。

1、1,一、面向对象程序设计理论,1.1面向对象的程序设计方法基础,1.2对象和类,1.3继承性,1.4重载,1.5多态性,2,1.1OOP基础,面向对象的程序设计方法(Object Oriented Programming)简称为OOP,它的基本元素是类(Class)和对象(Object)。,使用对象模拟自然的或抽象的实体,对用户掩盖了实现的复杂性(封装),并且能使程序员付出尽可能小的代价,获得尽可能大收益(继承),提高软件的开发效率。,3,1.2对象和类,类是对事物的特性及操作的抽象描述,对象是类的实体。,从C语言的角度来看,类是结构的自然演化,类就是包含数据声明和函数声明的结构。,类既包含了

2、数据又包含了代码,对类中成员的存取是受控制的,这一控制不仅针对数据,也针对代码,类的这个特性被称为封装。,4,计算过程的演变:手工计算全部手工和脑力完成计算器(面向过程)部分借助非人力因素,但仍需对过程进行控制和管理计算机(面向对象)完全借助非人力因素,运算一旦开始,可以无需人工的介入,封装的说明,5,特性:脚个数物理位置长度宽度高度形状,操作:搬动改造,类的说明,“桌子”类,6,定义类,class Counter long count;public:void SetValue(long);long GetValue();,关键字class引导类声明,Counter是类标识符,类体,分号,7,

3、使用类,类是一个模板,就象数据类型一样,使用的时候必须定义类变量。定义类变量称为类的实例化,类的实例化变量就是对象。,void main()Counter people;long value;people.SetValue(0);value=people.GetValue();,对象是具有某一个类所描述的共性的,但又有各自特性的个体。,8,类存取控制,类的成员的使用者有三类:1.类本身2.一般用户3.派生类每种使用者权限不同,对应与不同的使用权限,有不同的关键字说明。,9,类私有成员(private),类本身(或类的友元)可以存取类的私有成员。派生类不能存取其父类的私有成员。因为类必须在程序中

4、使用,所以类必须至少有一个非私有的成员。类成员的存取控制缺省为私有类型。,10,类私有成员(续),class PrivateClass long value;void f1();void f2();,void main()PrivateClass object;long l=object.value;object.f1();object.f2();,提问:上述程序可以达到预期效果吗?,类私有成员(续),11,类公有成员(public),在程序中使用给定类的对象,必须能存取成员数据、成员函数或两者。为使这些成员在程序中可以被存取,必须在类中声明公有部分。在公有部分定义的内容允许被其他对象无限制地

5、存取。通常可以有控制地使用公有成员存取私有数据,调用私有成员函数完成工作。,12,类公有成员(续),class PublicExamplepublic:int variable;void function();,void main()PublicExample object;int i=object.variable;object.function();,13,类保护成员(protected),class A protected:int value_a;class B:public A public:void FB();class C:public B public:void FC();,vo

6、id B:FB()value_a=0;void C:FC()value_a=0,14,问题,class A int value_1;protected:int value_2;void FA_1();public:int value_3;void FA_2();,class B:public Apublic:int value_4;void FB();,问:在类B的FB函数中可以直接存取的成员有哪些?问:通过类B的对象在程序中可以直接访问的成员有哪些?,15,特殊类成员,特殊类成员,1、构造函数(constructor),2、析构函数(destructor),16,构造函数,构造函数是用来建立

7、某给定类的对象的。一个类可以不定义构造函数,也可以定义一个或多个构造函数。编译系统保证类的构造函数先于其他函数被调用。,17,构造函数(续一),class Counter long value;public:Counter();Counter:Counter()value=100;,void main()Counter c1;return;,构造函数Counter()它有什么特点?,18,构造函数(续二),class Counter long value;public:Counter();Counter:Counter(int i)value=i;,void main()Counter c1(

8、100);return;,构造函数Counter()它有什么特点?,19,构造函数(续三),class Counter long value;public:Counter()Counter(int i);Counter:Counter()value=100;,Counter:Counter(int i)value=i;void main()Counter c1;Counter c2(100);return;,20,构造函数(续四),class Counter long value;public:Counter()value=100;Counter(int i=0)value=i;void ma

9、in()Counter c1;Counter c2(100);,问:Counter类是否能包含如上所示的两个构造函数?为什么?,21,构造函数(续五),class Counter long value;public:Counter(Counter,22,void main()Counter object(5);Counter object1=object;,构造函数(续六),这个等号表示复制构造函数,void main()Counter object(5);Proc_A(object);,把对象作为参数传递,也需要拷贝构造函数。,23,构造函数(小结一),1、缺省构造函数,2、有特定初始化值的

10、构造函数,3、通过复制另一个对象建立新对象的构造函数,24,构造函数(小结二),1、构造函数没有返回类型,2、构造函数与类同名,3、同一个类可以有多个构造函数,25,构造函数(思考题),class Counter long value;public:Counter();class Example int value;public:Counter c;Example();,void main()Example e;,在本例中,当c对象作为e对象的成员。问:c对象和e对象的构造函数的调用顺序是怎样的?,26,析构函数,析构函数在对象不再被使用时,执行一些必须的操作,一般是构造函数的逆操作。一个类只

11、能声明一个析构函数。析构函数是构造函数的逆函数。,27,析构函数(续),class Counter long value;public:Counter();Counter:Counter()printf(“”);,析构函数在声明和使用上有什么特点?,28,析构函数(小结),1、析构函数没有返回类型,2、析构函数的命名是在类名前加“”,3、一个类只能有一个析构函数,4、析构函数没有参数,29,1.3继承性,从编码角度讲,从基类中派生类以较低代价换来了大量的灵活性。一旦产生了可靠的基类,只需要调试派生类中所做的修改即可。派生类从它的父类中继承性质时,可使派生类对它们进行扩展、限制、改变、删除或不做

12、任何修改。所有这些变化归结成两类基本的面向对象技术:性质约束和性质扩展。,30,单一继承,class First int value_1;protected:int value_2;public:int value_3;,class Second:First int value_4;public:void F2();,问:在程序中可以访问的Second类的对象的成员变量有那些?,31,基类存取限定符,class First int value_1;protected:int value_2;public:int value_3;,class Second:public First int va

13、lue_4;public:void F2();,基类存取限定符,32,基类存取限定符(续),private:如果没有特别说明,private是缺省的限定符。基类中所有可继承的成员在派生类中都变成私有的。public:基类中所有public成员在派生类中仍为public成员,,33,构造函数的调用,class A public:A();class B:public A public:B();,如果现在将类B实例化成一个对象,构造函数的调用情况会如何?,34,构造函数的调用(续),类实例化时,需要调用其构造函数。如果该类是派生类,必须调用其父类的构造函数,如果其父类也是派生出来的,重复该过程直至到

14、达非派生的基类。,35,析构函数的调用,析构函数的调用顺序与构造函数的调用顺序相反。,36,构造函数的参数传递,class A public:int va;A(int i)va=i;class B:public A public:int vb;B(int i,int j)va=i;vb=j;,37,构造函数的参数传递(续),class A public:int va;A(int i)va=i;class B:public A public:int vb;B(int j,int i):A(i)vb=j;,38,派生类的类型转换,void main First c1;Second c2;First

15、*d1=new First;Second*d2=new Second;c1=c2;d1=d2;,如果这样则不行:c2=c1;d2=d1;,39,作用域的分辨,class A public:int get()return 1;class B:public public:int get()return 2;,void main()A a;B b;int i=a.get();int j=b.get();,40,作用域的分辨(续),class A public:int get()return 1;class B:public A public:int get()return 2;,void main(

16、)A a;B b;int i=a.get();int j=b.get();int k=b.A:get();,作用域分辨操作符,41,性质扩展,使用派生类的主要原因是基类提供了派生类需要的部分特征。常常基类很类似于需要的类,但不完全相同,其中有的函数需要稍微扩展一下。如果在派生类中再次书写整个函数会浪费很多时间。因此,可以充分利用类的继承特性,将函数的功能进行扩充。,42,性质扩展(续一),假设:有一个类A,它有两个成员函数,其中一个函数的功能的清屏,另一个函数的功能是用“*”画一条直线,直线的长度根据参数决定。现在需要一个新类B,希望它具有清屏的功能,同时具有用“*”画三角形的功能。,43,性

17、质扩展(续二),*n=7的直线*n=7的三角形,44,性质约束,用户常常找到一些基本合乎要求的类,但是它们可能会有一些不受欢迎的行为。这时,可以使用性质约束的方法来使派生类不具有某种功能。,45,性质约束(续),假设:有一个类A,同上例。有一个类B,具有用“*”画三角形的功能,但是它每次画三角形之前都会先清屏。现在需要一个新的类C,希望它具有类B画三角形的功能,但是在画三角形之前不会自动清屏。同时它依然保留单独清屏的功能。,46,多重继承,C+语言中,一个类的父类并不只局限于一个,实际上可以有多个,派生类可以从每个父类中继承性质。当然,这种继承性增加了语言和编译器的复杂性,但相比之下益处更多。

18、多重继承大大增加了类继承的灵活性。,47,多重继承的实现,假设:有一个类A,具有单独清屏的功能。有一个类B,具有用“*”画直线的功能,但是没有清屏的功能。现在需要一个新的类C,希望它具有用“”画三角形的功能,又具有单独清屏的功能。,48,多重继承的构造函数,class A;class B;class C:public A,public B public:C(int i,int j,int k),C:C(int i,int j,int k):B(j),A(i);,构造函数的调用次序是怎样的?,49,虚基类,class A public:int value;class B:public A;cla

19、ss C:public A,class D:public B,public C public:int get()return value;,这个value值从何而来?,50,虚基类(续一),class A public:int value;class B:public virtual A;class C:public virtual A,class D:public B,public C public:int get()return value;,51,虚基类(续二),A,A,A,B,C,B,C,D,D,52,1.4重载,在OOP中,简洁性是很重要的。用户使用系统时对系统了解得越少越好,调用函

20、数时需要的细节越少越好(参数的个数和类型)。如果函数能够接受各种类型的参数,由编译器区分细节,则会很方便。这个目的在C+中可以达到。但是重载并不是一个全新的概念。,53,重载(续),1、函数重载,2、操作符重载,非成员函数重载,成员函数重载,所谓重载就是同一个符号在不同的上下文中代表不同的含义。,54,重载非成员函数,void Display(char*string)void Display(long value)void Display(double value)void main()Display(“nPrint this,please!”);Display(123456789);Disp

21、lay(3.14159);,55,重载非成员函数(续一),void Display(char*string)void Display(long value)void Display(double value)void main()Display(333);,56,重载非成员函数(续二),void Display(char*string)void Display(long value)void Display(double value)void Display(float value)void main()Display(3.14159);,57,重载非成员函数(续三),void Display

22、(float value)int Display(float value)void main()Display(3.14159);,不同的返回值不能用来区分重载函数。,58,重载成员函数,class Example int value;public:void Value(int v)value=v;int Value()return value;,void main()Example e;e.Value(3);int i=e.Value();,59,类等级中的重载函数,class A public:int foo(int i)return i+1;class B:public A public

23、:int foo(float f)return f+10;,void main()B b;int i=b.foo(2);,到底应该调用A的foo还是B的foo?,60,类等级中的重载函数(续一),class A public:int foo(int i)return i+1;class B:public A public:int foo(float f)return f+10;,void main()B b;int i=b.foo(2);,这种情况不构成重载,61,类等级中的重载函数(续二),int f(A,i的结果是多少?,62,作用域分辨符,class A public:int foo(i

24、nt i);class B:public A public:int foo(float f)int foo(int i)return A:foo(i);,void main()B b;int i=b.foo(2);int j=b.A:foo(2);int k=b.foo(3.14);,63,参数匹配,参数匹配问题既重要有复杂。编译器遇到对重载函数的调用时,必须确定调用哪个函数。如果能找到参数完全匹配的函数,自然没问题,找不到时,则找一替代函数。此时,编译器将实在参数与所有重载函数的参数比较,这个过程叫作参数匹配。,64,参数匹配(续),1、类型转换不是非要不可的。,2、有时需要作参数升级。参数

25、可以沿路径charint long float double long double升级。,3、参数转换是可以的。参数可以根据标准或用户定义的转换规则进行转换。,65,重载操作符,class Example int value;public:void Value(int v)value=v;int Value()return value;,void main()Example e(?);e.Value(100+e.Value();,如果能这样:e=e+100;既直观又方便。,66,如何重新理解操作符,一元操作符 X X.();二元操作符 X Y X.(Y);,是一个操作符,但是也可以被理解为一

26、个成员函数。,67,重载操作符实例,class Counter int value;public:Counter(int i)value=i;Counter operator!()return Counter(!value);Counter operator+(Counter,void main()Counter c1(3),c2(5);c1=!c1;c1=c1+c2;,68,重载操作符实例(续),class Counter int value;public:Counter(int i)value=i;Counter operator!(int i)return Counter(!value)

27、;Counter operator+(Counter,放一个不用的参数可以吗?,返回类型为什么经常是对象类型。,c1+c2+c3+c4+c5,69,名字分裂及其规则,名字分裂的目的:使产生重载的符号在编译系统内部有唯一的名字,从而使得它们在目标代码中有不同的入口地址。名字分裂原则:函数名$q符号化的参数表void Counter:Value(int k)CounterValue$qi,70,1.5多态性,多态性是指C+的代码可以根据运行情况的不同执行不同操作。这通常不能由程序员来直接控制,而必须依靠面向对象的程序设计的特性,使对象对自身的运行进行跟踪。多态性是通过类的体系结构来实现的,不过,只

28、有类成员函数可以具有多态性,而不是整个类都具有多它性。,71,先期联编,class A public:void foo();class B:public A public:void foo();,int f(A,这个地方最终调用的是哪个类的foo函数?为什么?,72,迟后联编,如果在上例中需要f函数根据形式参数中传递进来的对象的类型自动调用该类的foo函数,则需要激活C+的迟后联编的功能,使程序在执行的过程中自动选择相应的函数。,73,迟后联编(续),class A public:virtual void foo();class B:public A public:virtual void f

29、oo();,int f(A,这时将根据实际的参数类型来选择相应的函数。,74,虚函数,声明为virtual的函数为虚函数。通过声明函数为virtual,来人为指定迟后联编。迟后联编只能用于类等级中的对象。对于不被任何类继承的类,声明其函数为虚函数,从语法上来讲是正确的,但是会引起不必要的运行时刻开销。,75,函数覆盖,1、虚函数的参数个数与类型。,2、虚函数的传递。,使用虚函数后,派生类中的函数可以覆盖原有基类中函数的功能,这被称为函数覆盖。构成函数覆盖的条件是:,76,抽象类,由虚函数的传递性可以看出,出现在类等级顶部及其附近的类常常有多个空的虚函数。如果一个类只有空虚函数,实例化这样的类有

30、意义吗?但是,这种实例化是允许的,其结果是得到一个占有内存却不做任何操作的无用的对象。为了避免这种情况的发生,C+中引进了可以被继承但是不能实例化的抽象类。,77,纯虚函数,至少包含一个纯虚函数的类被称为抽象类。,class A public:virtual void foo()=0;,注意纯虚函数的定义方法。,78,纯虚函数的使用,class A public:virtual void foo()=0;void main()A a;a.foo();,注意:抽象类不能实例化。,79,纯虚函数的使用,class A public:virtual void foo()=0;class B:public A public:virtual void foo();,void main()B b;b.foo();,注意:纯虚函数一定要被覆盖。,80,作用域分辨符,class A public:virtual void foo();class B:public A public:virtual void foo();,int f(A,此处调用的依然是A:foo()函数,而不是B:foo()函数,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 建筑/施工/环境 > 农业报告


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号