




已阅读5页,还剩73页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C+程序设计(part 2),OOP,What non-OO Solution,#include #define STACK_SIZE 100 struct Stack int top; int bufferSTACK_SIZE; ; void main() Stack st1, st2; st1.top = -1; st2.top = -1; int x; push(st1,12); pop(st1,x); ,bool push(Stack ,bool pop(Stack ,st1.buffer2 = -1; st2.buffer2 +;,_ _,OOP,OO Solution,#include #define STACK_SIZE 100 class Stack private: int top; int bufferSTACK_SIZE; public: Stack() top = -1; bool push(int i); bool pop(int ,bool Stack:push(int i); if ( top = STACK_SIZE-1) cout “Stack is overflow.n”; return false; else top+; buffer top = i; return true; ,bool Stack:pop(int ,#include #define STACK_SIZE 100 struct Stack int top; int bufferSTACK_SIZE; ; void main() Stack st1, st2; st1.top = -1; st2.top = -1; int x; push( ,X,bool push(Stack * const this, int i),bool pop(Stack * const this, int &i),this-,this-,this-,this-,this-,this-,this-,this-,st1.buffer2 = -1;,Encapsulation,Information Hidding,OOP,Concepts ProgramObject1 + Object2 + + Objectn Object: Data + Operation Message: function call Class Object-Oriented Object-Based Only Provide Encapsulation Without Inheritance Ada, etc,OOP,Why 评价标准 Efficency of Development Quality External Correctness、Efficiency、Robustness、Reliability Usability、Reusability Internal Readability、Maintainability、Portability,HUI UX,产品在规定的条件下和规定的时间内完成规定功能的能力 ( 概率度量:可靠度),需求 架构设计 构建模式 代码 测试用例 项目组织结构,OOP,Advantages 提高开发效率和软件质量 更高层次的抽象数据抽象 数据封装 更好的模块化支持(高内聚、低耦合) 软件复用(部分重用) 对需求变更具有更好的适应性,C+ vs Java,类,类 定义 class ; 组成 成员:成员变量、成员函数 成员变量:在类定义中给出的是声明 成员函数:在类定义中给出的是定义或声明 类成员的访问控制描述,类,class TDate public: void SetDate(int y, int m, int d); int IsLeapYear(); void Print(); private: int year,month,day; ;,类定义不完整,类,成员变量 声明 在类定义中对成员变量的说明是声明 不能赋值 在类定义中声明成员变量时不能初始化 引用或指针类型成员变量,类,class A; class B A a; /Error B b; /Error A *p; /OK B *q; /OK A /OK ,类型还未定义/未定义完全 只能声明成指针或引用,类,成员函数 在类定义中定义成员函数(inline) class TDate public: void SetDate(int y, int m, int d) year = y; month = m; day = d; int IsLeapYear() return (year%4 = 0 ,类,在类定义外定义成员函数,class TDate public: void SetDate(int y, int m, int d); void Print(); private: int year,month,day; ;,void TDate:SetDate(int y, int m, int d) year = y; month = m; day = d; void TDate:Print() coutyear“.“month“.“dayendl; ,a.h,a.cpp,类,成员函数的重载 遵循一般函数的重载规则 class A public: void f(); int f(int i); double f(double d); ; void main() A a; a.f(); a.f(1); a.f(1.0); ,类,对象 属性和行为的封装体 类的实例, 属于值的范畴 类属于类型范畴,用于描述对象的属性,构造函数,对象的初始化 描述 与类同名、无返回类型 自动调用,不可直接调用 可重载 默认构造函数: 无参数的构造函数 系统提供的默认构造函数 当类中未提供构造函数时,编译系统自动提供 参与对象的构造过程 通常定义为 public 有时也声明为私有的,其作用是限制创建该类对象的范围,即只能在本类和友元中创建该类对象,构造函数,构造函数的调用 创建对象时,构造函数将自动被调用,所调用的构造函数在创建对象时指定 class A public: A(); A(int i); A(char *p); ; A a1=A(1); A a1(1); A a1=1; /调A(int i) A a2=A(); A a2; /调A(),注意:不能写成:A a2(); A a3=A(“abcd”); A a3(“abcd”); A a3=“abcd”; /调A(char *) A a4; /调用a0、a1、a2、a3的A() A b5= A(), A(1), A(“abcd“), 2, “xyz“ ;,成员初始化表,成员初始化表 定义构造函数时,函数头和函数体之间可以加入一个对数据成员进行初始化的表,用于对数据成员进行初始化 class A int x; const int y; int public: A(): y(1),z(x), x(0) ;,成员初始化表,class A int m; public: A() m = 0; A(int m1) m = m1; ;,class B int x; A a; public: B() x = 0; B(int x1) x = x1; B(int x1, int m1): a(m1) x = x1; ;,void main() B b1; /调用B:B()和A:A() B b2(1); /调用B:B(int)和A:A() B b3(1,2); /调用B:B(int,int)和A:A(int) ,成员初始化表,在构造函数中尽量使用成员初始化表取代赋值动作 const 成员/reference 成员/对象成员 效率高 数据成员太多时,不采用本条准则 降低可维护性,成员初始化表,成员初始化表中的声明次序 成员初始化的次序取决于它们在类定义中的声明次序,与它们在成员初始化表中的次序无关 减轻编译系统的负担 注意类成员定义的次序,class CString char *p; int size; public: CString(int x):size(x),p(new charsize) ;,?,析构函数,析构函数 () 对象消亡时,系统自动调用,class String char *str; public: String() str = NULL; String(char *p) str = new charstrlen(p)+1; strcpy(str,p); String() delete str; int length() return strlen(str); char get_char(int i) return stri; ,Java: finalize(),RAII vs GC Resource Acquisition Is Initialization,析构函数,void set_char(int i, char value) stri = value; char ,拷贝构造函数,Copy Constructor 创建一个对象时,用另一个同类的对象对其初始化 自动调用 class A int x, y; char *p; public: A(); A(const A /拷贝构造函数,const可有可无 ,拷贝构造函数和,三种情况将调拷贝构造函数 case1 A a; A b=a; case2 f(A a); A b; f(b);,拷贝构造函数,case3 A f() A a; return a; . f(); 如果类定义中没有给出拷贝构造函数,则编译系统提供一个默认拷贝构造函数 默认拷贝构造函数的行为 逐个成员初始化(member-wise initialization) 如果相应的类有对象成员,则该定义是递归的,拷贝构造函数,class string char *p; public: string(char *str) p = new charstrlen(str)+1; strcpy(p, str); string() delete p; string s1(“abcd”); string s2=s1;,abcd,p,p,s1,s2,string:string(const string deep copy,悬挂指针,何时需要copy constructor?,abcd,动态对象,动态对象 在堆(Heap)中创建的对象称为动态对象 new /delete 单个动态对象的创建与撤消 class A public: A(); A(int); ;,为什么要引入new、delete操作符?,constructor/destructor,动态对象,A *p,*q; p = new A; 在程序的堆中申请一块大小为sizeof(A)的空间 调用A的默认构造函数对该空间上的对象初始化 返回创建的对象的地址并赋值给p q = new A(1); 调用A的另一个构造函数 A:A(int) delete p; 调用p所指向的对象的析构函数 释放对象空间 delete q;,动态对象,p = (A *) malloc (sizeof(A) free(p) malloc 不调用构造函数 free 不调析构函数 new 操作符 自动分配足够的空间 自动返回指定类型的指针 可以重载,动态对象数组,动态对象数组的创建与撤消 A *p; p = new A100; delete p; 注意 不能显式初始化,相应的类必须有默认构造函数 delete中的不能省,Const 成员,const 成员 const 成员变量 在成员变量的声明中加上const,则表示是常量 class A const int x; 初始化放在构造函数的成员初始化表中进行 class A const int x; public: A(int c): x(c) ,Const 成员,const 成员函数 class A int x,y; public: void f(); ; const A a; a.f() 合法? a是常量,在程序中不应改变a的值(改变a的成员变量的值) 如果A:f中没有改变a的成员变量的值,则是合法的,否则是不合法的,Const 成员,编译程序往往无法知道函数f中是否改变了a的成员变量的值 为了安全,编译程序认为a.f()不合法 a.f()合法 在A:f中不能改变a的成员变量的值 在f的定义和声明处显式地指出之 class A void f() const; ;,Const 成员,const 成员函数不能修改成员变量的值 成员函数加上const 修饰符的作用 调用点:告诉编译器该成员函数不会改变对象成员变量的值 定义点:告诉编译器该成员函数不应该改变对象成员变量的值,静态成员,静态成员 类刻划了一组具有相同属性的对象 对象是类的实例 类中声明的成员变量属于实例化后的对象,有多个拷贝 问题:同一个类的不同对象如何共享变量? 如果把这些共享变量定义为全局变量,则缺乏数据保护,,静态成员,静态成员变量 class A int x,y; static int shared; . ; int A:shared=0; A a, b; 类定义中声明的静态变量被该类的对象所共享 类的静态成员变量只有一个拷贝 静态变量也遵循类的访问控制,静态成员,静态成员函数 class A static int shared; int x; public: static void f() shared void q() xshared ; 静态成员函数只能存取静态成员变量和调用静态成员函数 静态成员函数也遵循类的访问控制,静态成员,静态成员的使用 通过对象使用 A a; a.f(); 通过类使用 A:f(); C+对类也是对象的观点的支持 在一些面向对象程序设计语言(如:Smalltalk)中,把类也看成是对象,其属性由元类(meta class)来描述 类定义中的静态成员就是属于类这个对象,静态成员,class A static int obj_count; public: A() obj_count+; A() obj_count-; static int get_num_of_obj() return obj_count; ; int A:obj_count=0; 类A是对象 obj_count:程序运行的某时刻存在的A类对象的数目 get_num_of_obj:获取A类对象的数目的方法,示例,class singleton protected: singleton() singleton(const singleton ,singleton,Resource Control 原则:谁创建,谁归还 解决方法:自动归还,友元,友元 类外部不能访问该类的private成员 通过该类的public方法 会降低对private成员的访问效率,缺乏灵活性 例:矩阵类(Matrix)、向量类(Vector)和全局函数(multiply),全局函数实现矩阵和向量相乘,友元,int ,class Matrix int *p_data; int lin,col; public: Matrix(int l, int c) lin = l; col = c; p_data = new intlin*col; Matrix() delete p_data; ,友元,class Vector int *p_data; int num; public: Vector(int n) num = n; p_data = new intnum; Vector() delete p_data; ,int ,友元,void multiply(Matrix ,友元,函数multiply中多次通过调用成员函数element访问m,v,r的元素 在一个类定义中,可指定某全局函数、某其它类或其它类的成员函数具有访问该类的私有和保护成员的权限 友元函数 友元类 友元类成员函数 友元的作用 提高面向对象程序设计的灵活性 数据保护和对数据的存取效率之间的一个折中方案,友元,void func() ; class B; class C . void f(); ; class A friend void func(); /友元函数 friend class B; /友元类 friend void C:f(); /友元类成员函数 ;,友元,class Matrix friend void multiply(Matrix 友元不具有传递性 示例:只能生成一个对象,原则,避免将data member放在公开接口中 努力让接口完满 (complete) 且最小化,class AccessLevels public: int getReadOnly const return readOnly; void setReadWrite(int value) readWrite = value; int getReadWrite() return readWrite; void setWriteOnly(int value) writeOnly = value; private: int noAccess; int readOnly; int readWrite; int writeOnly; ;,继承,继承机制 基于目标代码的复用 对事物进行分类 派生类是基类的具体化 把事物(概念)以层次结构表示出来,有利于描述和解决问题 增量开发,继承,基类与派生类(父类与子类) A是基类,B是派生类 class A /基类 int x,y; public: void f(); void g(); ; 数据 派生类对象拥有基类对象的所有成员 新的成员,class B: public A /派生类 int z; public: void h(); ;,继承,方法 不同名 同名 class B: public A public: void h() f(1); A:f(); void f(int); ; 重定义方法 虚函数,B b; b.f(1); /Ok b.f(); /Error b.A:f(); /Ok BAD,class A /基类 int x,y; public: void f(); void g(); ;,继承,protected 继承方式 public private、protected 访问控制调整 A:f1,继承,派生类对象的初始化 由基类和派生类共同完成 基类成员:由基类的构造函数初始化 派生类成员:由派生类的构造函数初始化 构造函数的执行次序 1.执行基类的构造函数 2.执行派生类成员对象类的构造函数 3.执行派生类的构造函数 析构函数的执行次序 与构造函数相反,继承,基类构造函数的调用 缺省执行基类默认构造函数 如果要执行基类的非默认构造函数,则必须在派生类构造函数的成员初始化表中指出,class A int x; public: A() x = 0; A(int i) x = i; ;,class B: public A int y; public: B() y = 0; B(int i) y = i; B(int i, int j):A(i) y = j; ;,B b1; /执行A:A()和B:B() B b2(1); /执行A:A()和B:B(int) B b3(0,1); /执行A:A(int)和B:B(int,int),虚函数,类型相容 类、类型 类型相容、赋值相容 问题:a、b是什么类型时,a = b 合法? A a; B b; class B: public A 对象的身份发生变化 属于派生类的属性已不存在 B* pb; A* pa = pb; class B: public A B b; A class B: public A 对象身份没有发生变化,虚函数,class A int x,y; public: void f(); ; class B: public A int z; public: void f(); void g(); ;,A a; B b; a = b; /OK, b = a; /Error a.f(); /A:f(),A /Error,把派生类对象赋值 给基类对象,基类的引用或指针可以引用 或指向派生类对象,func1(A,A:f? B:f?,虚函数,前期绑定(Early Binding) 编译时刻 依据对象的静态类型 效率高、灵活性差 动态绑定(Late Binding) 运行时刻 依据对象的实际类型(动态) 灵活性高、效率低 注重效率 默认前期绑定 后期绑定需显式指出 virtual,虚函数,定义 virtual class A public: virtual void f(); ; 动态绑定 根据实际引用和指向的对象类型 方法重定义,虚函数,如基类中被定义为虚成员函数,则派生类中对其重定义的成员函数均为虚函数 限制 类的成员函数才可以是虚函数 静态成员函数不能是虚函数 内联成员函数不能是虚函数 构造函数不能是虚函数 析构函数可以(往往)是虚函数,虚函数,后期绑定的实现,class A int x,y; public: virtual f(); virtual g(); h(); ; class B: public A int z; public: f(); h(); ; A a; B b; A *p;,创建一个虚函数表(vtable) 记录所有虚函数入口地址 对象的内存空间中含有指针,指向其虚函数表,B:f,A:g,b,x,y,z,B_vtable,p-f() (*(char *)p-4)(p),a,x,y,A:f,A:g,A_vtable,虚函数,class A public: A() f(); virtual void f(); void g(); void h() f(); g(); ; class B: public A public: void f(); void g(); ;, B b; A *p=,/ A:A(),A:f, B:B(),/B:f,/A:g,/A:h, B:f, A:g,class A public: virtual void f( ) ; void g() ; ; class B: public A public: void f( ) g(); void g() ; ; B b; A* p = ,/b.B:g,虚函数,纯虚函数和抽象类 纯虚函数 声明时在函数原型后面加上 = 0 virtual int f()=0; 往往只给出函数声明,不给出实现 抽象类 至少包含一个纯虚函数 不能用于创建对象 为派生类提供框架,派生类提供抽象基类的所有成员函数的实现,class AbstractClass public: virtual int f()=0; ;,虚函数,Figure,Rectangle,Ellipse,Line,virtual display()=0;,display,display,display,Figure *a100; a0 = new Rectangle(); a1 = new Ellipse(); a2 = new Line(); for (int i=0; idisplay();,class Button; / Abstract Class class MacButton: public Button ; class WinButton: public Button ; class Label; / Abstract Class class MacLabel: public Label ; class WinLabel: public Label ;,class AbstractFactory public: virtual Button* CreateButton() =0; virtual Label* CreateLabel() =0; ; class MacFactory: public AbstractFactory public: MacButton* CreateButton() return new MacButton; MacLabel* CreateLabel() return new MacLabel; ; class WinFactory: public AbstractFactory public: WinButton* CreateButton() return new WinButton; WinLabel* CreateLabel() return new WinLabel; ;,AbstractFactory* fac; switch (style) case MAC: fac = new MacFactory; break; case WIN: fac = new WinFactory; break; Button* button = fac-CreateButton(); Label* Label = fac-CreateLabel();,抽象工厂模式 Abstact Factory,虚函数,虚析构函数,class B ; class D: public B; B* p = new D; ?: delete p;,class string class B class D: public B string name; B* p = new D; ?: delete p;,虚函数,确定public inheritance,是真正意义的“is_a”关系 不要定义与继承而来的非虚成员函数同名的成员函数,class B public: void mf(); ; class D: public B ; D x; B* pB = ,public: void mf();,/B:mf,/D:mf,class rectangle public: void setHeight(int); void setWidth(int); int height() const; int width() const; class Square: public rectangle public: void setLength (int) ;,virtual,virtual,private: void setHeight(int ); void setWidth(int );,Penguin,class FlyingBird class NonFlyingBird,virtual void fly() error(“Penguins cant fly!“); ,void makeBigger(Rectangle ,assert(s.width() = s.height();,虚函数,明智地运用private Inheritance Implemented-in-term-of 需要使用Base Class中的protected成员,或重载virtual function 不希望一个Base Class被client使用 在软件”设计”层
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 舞蹈面试必 备:中国舞面试题目及答案全解析
- 知识题库-物业管理师考试题目及答案(填空题、单选题)
- 山西省大同四中联盟体2026届化学高一第一学期期末监测试题含解析
- 你的名字讲解版
- 天然药物化学萜类
- 湖北省襄阳市第四中学2026届化学高一上期中综合测试模拟试题含解析
- 氧气放散率讲解
- 市场营销消费者行为分析讲解
- 膝关节结核讲解
- 三级中医医院评审汇报
- 2025年(完整版)十八项核心制度培训考核试题(含答案)
- 社工的劳动合同范本(2025版)
- 2025年中国LCP料数据监测报告
- 纺织服装产业园项目建设方案
- DB44T 1597-2015 电镀水污染物排放标准
- 儿童保健工作管理办法
- 全固态高功率超快激光器:放大机制与热透镜效应的深度剖析
- KET教学课件新版
- DGTJ08-2232-2017 城市轨道交通工程技术规范
- 中职思政试题及答案
- 中小学暑期安全教育班会课件
评论
0/150
提交评论