



下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
ー、 C++概述C++Primer程序员面试宝典CC++.发展史1980BjarneStroustrup在C语言基础上加上面向对象的程序设计物色,成就了后面的C++语言。ANS!和ISO1998正式推出C++国际标准。.C和C++的基本区别C++是C的超集,C是C++的子集:C++编译器(g++)能够编译任何C程序。源程序扩展名:.cpp.ccC程序是.c库头文件不再明文的加.h后缀,并且兼容C的头文件,方法是将:#include<stdio.h>♦#include<cstdio> 〃头文件名前加c,省略.h标准10由stdio.h变成了iostream类标准格式化函数升级为cin,cout相关类new/delete取代了malloc()/free(),增加了构造/析构函数调用处理机制.C++增加的内容BOOL类型和宽字节字符类型的支持(wchar」)名字空间是ー种描述逻辑分组的机制,是ー个作用域。程序里每个实体(函数,类)都属于某个可识别的辑逻单位(模块),即是说它们都应该位于某个名字空间。它为更好的组织某ー集团的组成成员提供了更大的灵活性,例ー个类的实现,成员函数没有必要都在一个花括号作用域里去实现,可分散开来,前提是加上名字空间限定,例:voidclassA::func()“。〃classA是具体类的名字空间,::是限定运算符,表示从属关系,即func()属于classA类型转换和强转static_cast数值类型之间,有一方是void・的指针类型之间(静态转换,程序未运行时开发者即已确定所要的类型,编译时确定类型)dynamic_cast多态情况较常用(动态转换,即在程序运行时オ确定具体形态)const_cast去掉const、volatile关键字的限定作用reinterpret_cast允许强制转换任何类型的指针;把整数强转为指针,指针强制为整数。具体目标类型标识符(待转对象) る强制类型转换,让编译器不会产生警告信息。尽量少用强转。内联函数它保持了函数的所有特点,但在需要时可像宏一样展开,不需要调用函数的开销(它是在编译时展开的)。行为像宏一样,加速的函数(不需调用),效果仍是函数。内联函数会帮用户进行类型转换或检查,表达式优先序处理,比宏更安全。加了inline表示申请为内联函数,但编译器不一定会通过,要看函数体是否过于复杂(递归函数一般没法成为内联函数)。另外类的成员函数声明和函数实现在ー起时也会自动申请为内联函数,但能不能成功升级也要看编译器。成员指针它主要用来访问某个数据或逻辑实体的内部成员。成员指针也就是一个成员地址,两者都是采相对地址(类似偏移量的概念),成员函数地址特殊看待处理。具体参考06memberpointer.cpp□函数重载和默认值在C++中,允许有相同的函数名,不过它们的形参列表中数据类型不同,这样这些函数就可以相互区别开来。这在C语言中是不允许。在C++中函数重载是通过额外底层处理实现的,例如:voidshowMe();voidshowMe(intival,intiva12);在底层会转为:—Z12showMe _Z12showMeii由上可见,在C++编译器看来,这两表面看起同名的函数,最终还是两个不同的函数。C++函数取消了隐式函数声明,另增加函数形参默认值机制extern"C”{…}用来告诉编译器,用C语言方式进行相关代码的编译处理。达到新旧代码兼容的目的。・引用及在函数中的应用(const)面向对象思想类的实现(struct/class),构造函数引用型变量引用型变量是其他变量的ー个别名,我们可以认为它们只是名字不相同,其它都是相同的。它没有独立的内存空间,它必需与变量共享。它不能超越变量的权限属性。是ー个从属地位。引用的初始化。一般要求声明一个引用变量,需要给它ー个初始值,在引用变量的生存周期内,该值不会改变。引用的定义格式:[const!数据类型&引用标识符=宿主变量;引用在函数传参中是以变量自身作为传参对象。引用作为返回类型时注意不要返回一个局变变量,而应该返回ー个局部静态变量的引用或动态分配空间的指针引用。例:int*pi=NULL;int*&rpi=pi;//rpi就是ー个指针引用变量C++中尽量使用引用。引用是用指针实现。数组不需要用引用,因为数组本身就是ー个内存首地址。基本数据类型数据量不大时,一般不加引用。在形参中能加上const,就尽量加上,防止误改实参变量的值(自我约束)。C++规定,如果不用引用,就潜意识的表示需要把数据复制一份,如果有引用不加const,就意味着我们可能要改变变量的值。形参用引用可提高传递值的效率,加上const又能保护实参,比起直接传递变量值好得多。返回引用类型其实是返回变量自身,所以可以充当左值进行运行二、面向对象.对象:它是客观世界中的物体在人脑中的映象(映射,印象)及人的意向(行为)分映象:数据意向:方法(函数,功能).对象是可以分类(归类,归纳,抽象)理解的,即可以举一反三的去看同类事物つ类(同一类型对象的蓝图,抽象集合).面向对象:帮开发者更好,更快,更强,更易的解决一整片的问题,管理代码,代码复用。它符合人对事物、问题的认知规律,可以更好的解决问题,关注问题,而不是具体技术细节的实现,即不需要太多的技术转换。(同类问题的解决方案).类,是用户定义的数据类型它含有数据成员(变量),成员函数(方法).可以用类来声明变量(实例)。每个实例是类的ー个对象。定义类的实例可称为类的实例化(注意与初始化的区别)。.定义类:struct(成员默认是公开)(对于C来说,它是ー个升级版)class(成员默认是私有)三.THIS指针l.this是系统自动配置的只读指针,指代本类自身.它的值是本类对象的首地址.this->age指出age是mm内部的ー个数据成员.this作用域只限在类mm普通成员函数内部,从本质上看,它是ー个具体成员函数的局部指针变量四.构造函数(初始化助手)在类中,函数名和类名相同的函数称为构造函数。主要来用给刚刚分配好空间的对象的数据成员进行初始化工作(清理垃圾数据,给const,引用数据成员进行初始化)〈注意将初始化跟赋值运算相区分>.不要指定构造函数的返回值类型,即使void也不可以。构造函数没有返冋值类型.构造函数的初始化,初始化列表,对象的初始化.使用默认参数的构造函数.默认构造函数至少提供ー个构造函数,如果没有,编译器会自动产生默认的构造函数(它什么事情都不做,空函数).重载构造函数类中可以有多个构造函数,重载的意义在于接受不同参数的初始化要求。.拷贝构造函数它仍然是ー个构造函数,它的特点是参数是本类对象,实现成员的复制,如果有指针成员,需完成动态空间的分配和初始化,空间内容的复制。用户自定义拷贝构造函数的时机:要求实现深拷贝时(与浅拷贝相反,它能实现对目标对象指针成员所指向的动态空间内容进行新对象的空间分配和内容复制)。默认的拷贝构造函数:如果没有写拷贝构造函数,编译器也会自动产生一个拷贝构造函数(它不是空函数,它会完成所有成员的逐个复制,但它只能进行浅拷贝〈它不会帮用户把指针成员所指向的动态空间进行动态复制,有隐患〉)它作用的地方:初始化,参数,返冋值。(注意跟赋值运算)五.CONST对象和CONST成员函数CONST对象:如果ー个对象被声明为只读对象(常量),那么该对象就只能调用类当中的CONST成员函数(例外:被编译器隐式调用的构造函数和析构造函数)。它在形参中出现的频率非常高。CONST成员函数:成员函数声明后边加上const关键字就表示了一个CONST函数。这样的函数承诺不修改对象中数据成员的值,而只是访问,读取操作。加了CONST的成员函数使用范围是被放大而不是缩小。CONST引用,CONST成员函数与CONST对象都在遵守H我约朿的原则。普通对象可以访问CONST成员函数和其它成员函数。附注:CONST成员函数和同名的普通成员函数会构成重载现象。对于普通的对象,它优先选择非CONST的成员函数MUTABLE:在CONST成员函数里如果要破例修改某个数据成员,可在数据成员声明处左边加上本关键字。加了MUTABLE的数据成员不受CONST约束。一般用于统计不限CONST的本类对象的数据。例:staticmutablelongmmCount;〃不单能统计普通对象,也要将CONST对象纳入统计范畴。六.析构函数(善后助手)当ー个类的对象离开作用域时,析构函数将被调用(系统自动调用)。析构函数的名字和类名ー样,要在前面加上〜。对ー个类来说,只能允许ー个析构函数,它不能有参数(没有办法函数重载),也没有返回值。它的作用是完成一个清理工作,如释放从堆中动态分配的内存。.默认析构函数,如果用户没有定义,系统会自动分配ー个,它什么也不做。.用户自定义析构函数的时机:如果数据成员含有指针,并且在堆中动态分配了内存,由于系统不会帮用户自动释放,故这时析构函数需要由用户自定义。七.赋值函数(operator=)赋算运算:给ー个已存在的变量实例赋上新的值(即是说如果变量是个指针变量并且指向了一片动态空间,这里赋新值的时候勿忘先回收旧的内存空间)。判断是不是赋值运算:对象是否已定义,并且是在正常的情况的情况下声明定义,并做过初始化工作。八.静态成员static可以把类的成员声明为静态的,这样的静态成员它只能存在唯一的实例(只能初始化一次)。所有的成员函数都可以访问这个的静态成员。即使没有声明类的任何实例,静态成员也已经是存在的。不过类当中声明静态成员时并不能自动定义这个变量,而必须在类外部来定义它(初始化)。静态成员不依赖任何本类对象而存在。(一个静态成员给多个本类对象共享的关系).静态数据成员:它是全局变量,但仍然受类的权限约束,如果是private,则只有类的对象成员函数能访问和修改它。如果是public,则不限类对象,甚至没有对象也可以访问修改。.静态成员函数:给ー个成员函数最左边加上static,就成为了一个静态的成员函数。如果一个成员函数不需要访问类的任何实例成员(非static成员,具体对象的数据成员和成员函数),就可d以给它提升为静态成员函数。它也是不依赖任何本类对象而存在,可用类名或对象名限定来调用它。像:类名::静态成员称为静态调用.静态成员因为不依赖任何本类对象,所以它也不存在THIS指针.使用静态成员的时机:当需要管理或统筹本类的各个对象各种状态或行为时,我们就要用它。九.临时对象(匿名对象)只使用一次的对象,将名字去掉或者说没有名字的对象,没有进行空间的动态分配。C++建议多用临时对象。编译器一般会对这样的对象进行优化,例如:mmmeimei=mm(“2011","郭美美”);〃mm*meimei2=newmm("2011","郭美美“);〃上边的临时对象是自动对象(自动变量)。跟本句可类比学习(形态)。不代表newmm(…)是临时对象。〃mmmeimei("20U","郭美美");〃有名字,不是临时对象经常用在初始化,传参,返回值的应用上。可类比字符串常量的使用。十.运算符的重载C++允许为类的对象构造运算符来实现单目或者双目运算,这个特性就叫运算符重载。但注意运算符不能是用户新创立的,而只是已有的。可以通过添加成员函数或友元非成员函数两种方式来实现运算符重载。它存在的意义是允许用户用自己的思路去改变这些运算符函数的默认用法。.重载运算符的时机:需要在定义的对象间相互赋值时,重载赋值运算符。需要在数字类型增加算术属性时,重载算术运算符。需要为定义的对象进行逻辑比较时,重载关系运算符。对于CONTAINER(容器类),重载下标运算符口,&,*,()。需要从I/O流中读写对象时,重载<<和〉〉运算符。重载成员指针运算符ー〉以实现智能指针。在少数情况下(类内部进行局部空间管理时)重载new,delete运算符除了单参数构造函数可以实现隐性类型转换,运算符重载也可以实现强制的类型转换,这时不需要加返冋类型。其它运算符不重载:::. .* ?:sizeoftypeid.重载运算符的规则:不能违反语言的语法规则如果ー个运算符可以放在两个操作数之间,就可以重载它来满足类操作的需要,哪些这种用法原本为编译器不能接受的。不能创造C++没有的运算符,ー些禁止重载的不要去重载重载时不能改变运算符的优先级和结合性.运算符重载的格式:成员函数:表达式的数据类型operator具体的运算符(右值非本类数据形参)友元非成员函数:friend表达式的数据类型operator具体的运算符(左值本类形参,右值非本类数据形参)friend表达式的数据类型operator具体的运算符(左值非本类形参,右值本类数据形参)例:mma=b+3;//b+3 b是本类左值的情况:つmmoperator+(intival);friendmmoperator+(mmmL,intiR);mma=3+b;//3+b 就只有一种重载方式つfriendmmoperator+(intiL,mmmR);单目运算符的格式:成员函数:运算符在左边:表达式的数据类型operator具体的运算符()运算符在右边:表达式的数据类型operator具体的运算符(int)〃这里加的int是哑元,只是用来区别运算符在左边的情况,不需要对它进行调用,不需要形参标识名。友元非成员函数:运算符在左边:friend表达式的数据类型operator具体的运算符(操作数形参)运算符在右边:friend表达式的数据类型operator具体的运算符(操作数形参,int)〃没法直接在操作数类内部进行成员函数编写的时候,可在类外部声明和定义,把friend拿掉,通过操作数的成员函数进行数据访问和修改。非成员函数不需要给函数末加上const重载中需特别注意的:a.注意检查是否需对形参引用及返回值引用作CONST限制(后续效应)b.注意查看重载的运算符函数到底有没有在修改本类对象的数据成员,没有则给函数加上CONST。这很有必要!(技术因素)c.运算符到底用不用修改到对象本身的值,还是只是加以运算处理,直接把处理结果返回。(整体效果)作业1:写ー个学生考卷答题类(高考答题卡,只有一个大的选择题,每题有四个选项,总数有30题)。实现它的答题操作(每ー题学生选了哪个选项),学生数据要有:姓名,班级,学号,学校,分数。要求老师可在学生类里评分,浏览学生答题结果,可以查看所有学生的平均分数,参考学生人数。要求用OOP思想进行类的编写。作业2:实现ー个string类,这个类可以进行=,+,«,»,length()oH一.面向对象继承继承可以使一个新类(子类,派生类)获得其原有类(基类,父类)的操作方法(protected,public成员函数)和数据结构(protected,public的数据成员),新类中只需增加父类中没有的函数或自己的数据结构即可。.类空间的说明ー个结构或者类,不管里边有没有成员,至少占用ー个字节(如果类有一个整型成员,则类就是占用4个字节)。以上如果存在至少一个虚函数,则至少要占用4个字节。(因为这时类会隐藏ー个虚表指针)课タトTIPS:classa{voidfunc(a*this){};}//this指针定义的地方,看不见,是隐性的.继承方式权限关键字在类声明中:public:本类成员,子类,本类对象(在外界)都能访问protected:本类成员,子类可以,!本类对象(在外界)不可以privateI本类成员可以,子类,本类对象(在外界)不可以2.1.2在类继承中的作用:子类继承方式、父类中声明权限publicprotectedprivatepublic继承publicprotected不继承(隐藏)protected继承protectedprotected不继承(隐藏)private继承privateprivate不继承(隐藏)注:继承方式的权限关键字说明了子类继承父类的代码将进行权限更新,最大权限限制为所注明的权限关键字(只会降级,不可能升级)2.2继承的格式class子类名:权限关键字父类名1,权限关键字父类名2〃末尾没有分号声明一个类:class类名;在调用(形参)声明:例:voidfunc(classclassNameobjectName);.继承中的构造和析构函数的调用可在子类的初始化列表中显式调用父类的构造函数(仅有的ー种方式)如果没有显式的调用父类的构造函数,系统也会自动隐式的调用父类没有参数的构造函数父类的析构函数也会被自动调用。构造调用顺序:先父类构造,再子类构造析构调用顺序:先子类析构,再父类析构构造,析构函数和赋值运算符函数子类不可能继承父类的,因子类自己一定也要有一套这样的函数.成员函数和名字隐藏子类与父类同名的函数:出现同名,则父类函数会被隐藏(屏蔽,父类函数继承仍然存在):如何再次调用父类的同名函数?例:mm::showMe();如何在外部用对子类对象调用其父类的同名函数?例:ranjing.mm::showMe();静态成员函数的继承处理:仍然可以被继承到子类.加了private的静态成员又如何处理?仍然无法继承。但是public的静态成员就可以正常继承。名字隐藏:即是解决同名情况下,如何优先处理的问题。子类同名函数优先于父类同名函数。.多重继承ー个子类可以有多个父类,而父类之间既可以是有血缘关系的,也可以是没有血缘关系。多个父类按继承顺序执行构造函数。析构则反方向自动执行。多重继承里,如果父类存在虚函数,则子类会继承多个对应各个父类的虚表,并会有多个的虚表指针(隐藏的,而且指针一般会存在对象的首地址位置,每个指针占用4个字节)多重继承的父类间的成员冲突:a.子类仍然可以继承这些父类同名函数,只是在调用(运行,执行)时,需要给子类对象指明要应用哪个父类的同名函数,例:ranjing.mm::showMe();ranjing.mm::showMe();优点:个性保留 缺点:调用不方便b.将父类的同名成员抽象(移植)到更高层的父类间的共同爷类(父类的父类),并且父类采用虚继承的方式(在public前加上virtual)〇虚继承能保证这个爷类在多个继承类中只保留一份(数据和方法)(可类比类的静态成员,只有一个实例)。优点:不再有冲突缺点:这样的函数只有一个,不再有不同的个性。虚继承中的基类(爷类)的构造函数由底层子类直接调用。虚继承形象理解为静态继承(只有一个实例)加了virtua!关键字不代表就什么都是虚函数那样的概念组合(聚合)与继承的区别和共性组合是将其它类对象作为本类的成员对象(数据成员),像string类,list类。将它们集成在自身上面,没有什么继承关系,只是拥有这些类成员的功能和属性。继承:子类isa父类类型 组合:本类hasa(some)其它类十二.面向对象多态.多态和虚函数多态:同一个接口标准,多种实现方式,具体表现形式可依据所接入的对象类型得以呈现,这样的ー个情况可称为多态。例如:ー个USB接口(父类的ー个或多个虚函数。接口更切确的概仿是纯虚函数),多种USB设备(在这个接口上的子类功能实现)。父类的行为mostlikesa子类(具体功能有赖于子类功能的实现,多态实现的效果:父类指针能调用子类的函数)多态是目标,蓝图虚函数:如果父类调用函数的时候希望根据实际情况(更具体的对象类型,子类类型),来调用最恰当的子类函数,则需要在父类的同名函数声明前加上virtual,这样的同一组(父类,子类)同名函数都可称为虚函数(即使子类没有加virtual也ー样,只要父类有加即可)。虚函数是实现多态的手段,载体。多态是父类指针或引用指向子类对象(多态只能用指针或引用来实现)在构造和析构函数中调用虚函数的时候没有多态,因为子类还未产生。具体调用哪个类的虚函数,是由指针或引用所指向的对象类型来决定的,而不是指针或引用自身的类型。(指针存的地址是子类的具体地址,虚函数地址是偏移量)虚函数子类重写后仍然是虚函数,加不加virtual都一样。虚的析构函数:在父类的析构函数前加virtual,使之成为虚的析构函数。它的作用是让父类指针能依对象实际类型去找对应子类的析构函数进行析构(得以由子类到父类按顺序层层析构,不然就只能析构父类本身而已,有隐患)。(多态行为)如果类存在虚函数,就一定要把析构函数变成虚的析构函数析构函数可以是虚函数,但不能是纯虚函数,构造函数连虚函数都不可以是(原因:子类对象都不存在,父对象如何多态?)。2.纯虚函数和抽象类纯虚函数:一个虚函数不需要或不能写出任何实现的时候,可以定义为纯虚函数:virtualvoidfunc()=0;〃后边加上=0就是纯的purevirtual纯虚函数要在子类中进行实现,在子类中降级为虚函数,如果子类也没有实现这个纯虚函数,则子类也不可实例化,即它也是抽象类。(继承在作怪)抽象类:永远不需要实例化的类可定义为抽象类(定义:在里边加上纯虚函数,只有接口声明,没有实现),一般作为接口说明类。它不能实例化,但可以定义它的指针或引用来实现多态调用。.静态绑定和动态绑定(动态联编)〈多态发生的时机〉静态绑定:通过对象名使用圆点符号调用函数时,调用哪个已是在编译时就已确定的,称为静态绑定。即使调用的是虚函数,也不能实现多态.(对象变量不能存子类对象的地址,没法调用子类函数)动态绑定:父类指针或引用通过指向子类对象的首地址,及虚函数的地址(偏移量),动态选择正确的子类虚函数。这种执行时选择合适的调用函数称为动态绑定。(多态行为只是存在虚函数之间,不包括普通函数的调用〈指针是什么类型就调用什么类的普通函数〉)类型信息和转换:dynamic_cast的用法运算符typeid(火眼金睛).多态的底层实现(虚函数表)虚函数表指针:它处于对象的首地址位置,如有多重继承则有多个的虚表指针,且指针定义依父类自左向右由上而下。(跟虚继承表有区别?)虚函数表的结构:它记录了一个父类和本类所有虚函数的实际地址。它比较像ー个数组,下标值是虚函数偏移量(成员指针地址),数组每ー个元素存的是对应函数的真实地址值(地址值,不是指针类型,没有什么类型区别)。多态调用的流程:通过父类指针指向子类对象首地址(真实地址),实现动态绑定。调用具体的虚函数(不是普通的成员函数)时先得到子类对象的虚函数表的指针值(真实地址),访问子类对象虚函数表结构(数组),依据虚函数的偏移量得到其真实的函数地址(数组元素的值),再通过这个真实的函数地址进行调用。过程资源开销较大,实时项目一般要避免使用过多的多态调用。SVN(subversion)CVS GDBQT十三.I/O输入/输出流.标准输入输出cout输出到标准显示器,有缓冲,可重定向缓冲好处:快显时可减少闪烁.缓冲输出时机:遇到换行、有输入、flush、缓冲区已满、程序结束cerr输出到显示器,无缓冲,不可重定向(要求实时输出)clog输出到显示器,一般无缓冲,类似cerrcin标准键盘输入,有缓冲.输入输出流的类的层次结构istreamostreamistringstreamostringstreamistreamostreamistringstreamostringstreamifstreamofstream.非格式化输入输出.get().put()读取、输出ー个字符〃getchar()putchar().getline()〃可接数组,可接string〇数组输入放不下时会出错.ignore。忽略若干字符,不加参数表后边字符全忽略.putback。退回ー个字符,peek。査看下ー个要读取的字符(还是没有读取出来,只是看ー下,可预处理,辅助判断),clear。清除错误状态码,不是用来清除缓冲区。输入输出对象一旦处于错误状态,就不再读写。eof()是否结束(文件)fail。是否失败(状态错误)bad。错误是否不可恢复good。是否状态良好.字符串的输入输出istringstream(可用来写解码器)ostringstreamsstream.str()可转存为string类附加知识://string类常用成员函数://c_str()转换成constchar・类型//find。查找关键字对应的下标值〃sub_str()截取子字符串〃length()获取字符串长度〃[下标值]可将对象像数组那样取字符元素,例:str2[3]//replaceO?替换目标字符串为关键字//+运算将左右两个字符串合在ー起例:stringa="123",b="456";a+b;.文件的输入输出ifstream 只读操作读光标ofstream 只写操作写光标fstream 读写一体操作有两个光标,读光标,写光标打开文件:[ifstreamIofstreamIfstream]文件对象名(文件字符串,[打开模式]);读操作:.read(内存首地址,字节数);写操作:.write(内存首地址,字节数);//fwriteC++规定:10操作的!内存地址用char・类型,故要做(char*)转换上述两个函数是在istream和ostream中定义的,所以也可以用cin,cout来调用上述两个函数不关心数据类型,只关心数据块在什么位置,多少字节文件关闭.close()文件控制:C++文件内可以有两个位置指针,一个负责读g,ー个负责写p.gcount()取得最后一次读到的字符个数,tellgO 获得当前读的文件指针位置(读光标).tellp() 获得当前写的文件指针位置(写光标).seekg()设置当前的读的文件指针位置(读光标).seekp()设置当前的写的文件指针位置(写光标)文件打开模式:ios::binary二进制模式ios::in读ios::out写ios::app追加 ios::trunc清空原文件//ios::ate以上可用I叠加合用 fstream(文件名,打开方式)文件位置指针(光标)参考位置:ios::beg文件开头位置 ios::cur文件当前位置ios::end文件末尾位置可选作业:写ー个网页代码解码器,用istringstream类作业:写ー个使用公式的加解密算法,进行文件存取操作,文件内容可自定。.格式化的输入输出需要用到的头文件iomanip.hcout.width(x);设置最小宽度,只管ー次cout«setw(x);指定宽度cout.precision();取得精度cout.precision(x);指定精度cout«setprecision(x);如果指定fixed,就为指定小数点位数cout.fill(char);以字符作为空白处的填充cout«setfill(char);设置函数和标志位关键字cout.flags(格式标识符);添加标识cout.setf(格式标识符);添加标识cout.unsetf();清除标识设置以下关键字可直接加在<<右边使用而无需.setf(关键字);left左对齐right右对齐interma!两边对齐boolalpha用true和false表示bool输出dec十进制hex十六进制oct八进制scientific科学计数表示fixed普通小数表示showbase输出前缀showpoint显示尾〇showpos正数前面加+号uppercase将输出的字母全转成大写输出unibuf一次输出操作后刷新十四.异常处理异常:在程序遇到ー个无法解决的问题时,一般系统就会自动抛出对应错误类型的异常对象。默认情况下,比较严重的异常会直接调用std::terminate()函数,即中断退出。异常(throw)即可以由系统自动抛出,也可以由用户依实际情况人为抛出。抛出的异常对象也可以由用户获取(catch),获取后用户可以自定义是要直接处理,还是向上一级(不是向后边的catch抛)继续抛出。产生异常的代码异常对象抛出后,代码后面的语句也就无法再继续运行。(栈回退机制).抛出异常函数声明异常格式:返回类型函数名(形参列表)throw(异常类型可变参数列表く可以没有参数〉);throw(列表):表示可抛出的异常类型有哪些(列表)。throw():表示不抛出任何的异常类型(有异常则交由系统默认处理)连throw。都没有:可能抛出任何类型的异常注:如果有一个异常未捕获,就会异致std::terminate()函数调用抛出异常语句:throw异常对象(变量,临时对象)或常量;(手动抛出)系统自动抛出,也会有对应的异常类型对象.捕获并处理异常捕获格式:try{可能产生异常的代码群} 〃尝试在花括号作用域内获捉异常(撒网)catch(异常类型异常对象形参){处理代码;[throw;/・原来的异常对象重新向上层抛出・/Ithrow具体异常对象];}〃捕获对应类型的异常对象(收网)catch(异常类型异常对象形参){处理代码)catch(...){处理代码}〃...表示其它异常类型(终极异常捕获器,缺点是无法识别异常错误类型。一般作用是做些重要数据保存工作,然后退出或再抛出异常由系统处理).异常导致的ー些内部联动环节:异常会导致堆栈的回退,申请的ー些资源会自动调用析构函数,成员变量等资源会释放回收(指针成员要特别注意)对象在创建过程中,在构造函数中出现异常,则已经申请到的堆内存可能不能释放(析构函数无法自动调用)。解决办法一是不要在构造函数中调用过多的会出现异常的函数。解决办法二是建立托管指针成员auto.ptr。它能自动帮用户处理指针所指向的空间释放问题。(析造函数无需再加相关的delete语句)。(auto_ptr实现原理,它自己是所用类的ー个变量成员,变量是由类的栈结构自动管理释放的,释放时会调用auto_prt变量的析构函数,在这个析构函数中有delete所托管指针空间的语句〈多态〉,所以可达到自动释放所托管的指针成员的目的).虚函数覆盖时的异常描述:C++规定子类函数至少是受到父类函数的异常描述列表那样的限制(可能要受到的限制更严格)classaPublic:Virtualvoidfl();〃抛出多个异常Virtualvoidf2()throw(类型1,类型2);Virtualvoidf3()throw(类型1););Classb:bublica{Public:Virtualvoidfl()throw(类型1);〃编译器可通过Virtualvoidf2()throw(类型1);//比父类更受限,也通过Virtualvoidf3()throw(类型1,类型2);〃编译器不通过,比父类限制松了,不行!);.标准库异常类以下异常类的头文件是stdexcept.hrunti»e_erroroverflo>_error underf1ow.errorexceptionrunti»e_erroroverflo>_error underf1ow.errorexception.标准异常在的继承写法:直接承继exception类,一般只需复写ー个成员函数即可:constcha*what()constthrow(){return异常描述字符串;}〃用来说明所出现的异常错语问题是什么.不再抛出异常。十五、数据结构数据结构是我们整个软件项目最终实现品质好坏的一个基本前提条件,算法也是依赖于我们选择了怎样的数据结构。一旦确定好数据结构,算法及其它框架设计相应也就比较的轻松了。(大厦的地基).数据结构:是指同一数据元素类中各数据元素之间存在的关系。.四类基本结构及存储方法:集合(例:红,绿,蓝就是ー个颜色集合,同一类之间没多大关系)、线性结构(ー对ー的关系,例课程表),树形结构(一对多的关系,家谱),图状结构(网状结构,多对多的关系,顶点(结点)与边的关系,例地理交通图)。 (逻辑关系)顺序存储:逻辑相邻与物理存储一致,例数组链式存储:逻辑相邻与物理存储不一致,它主要通过节点间的指针来联系相邻的节点,例链表(类似火车,车厢间用挂钩<指针〉连接)索引存储:除建立存储结点,还建立除加的索引表来标识结点的位置(地址),例:新华字典的索引表散列(HASH,哈希)存储:就是根据结点的关键字直接计算出该结点的存储位置(地址)。 (存储关系).数据处理:査找,插入,修改,删除,遍历,排序,统计及其它ー些计算。 (数据结构上的算法)4,常用的数据结构:数组(Array)链表(LinkedList):类比火车〈结点间通过指针联系〉栈(Stack):类比水杯〈后进先出〉队列(Queue):类比水管〈先进先出〉树(Tree)く重点:搜索ニ叉树(有大小顺序〈左枝小于根结点,根结点不小于右枝〉,只有两个分支)〉:结合了排序数组和链表(可伸缩性,不限元素个数)的双重优点图(Graph):是由结点和有穷集合V和边的集合E组成。研究的是两个结点(顶点)所具有的相邻关系(边)。堆(Heap):它是ー种特殊的ニ叉树形数据结构,每个结点都有一个值。堆的特点是根结点的值最小(或最大),且根结点的两个子树也是ー个堆。散列表(Hash,哈希表):若结构中存在关键字和K相等的记录,则结构的相关记录必定在f(K)的存储位置上。十六、算法算法是在有限步骤人求解某ー问题所使用的ー组定义明确的规则(功能函数,程序)。它一般要以数据结构为基础,建立在上面的算法有时是有很大区别的,即算法有各种各样的实现方法,同时亦有好坏之分。.算法的五大特征:参数输入(ー个算法可以有0个或多个输入参数,以确定运算对角的初始情况,所谓。个输入是指算法本身定义了初始条件)、结果输出(一个算法有一个或多个输出,以反映对输入数据加工后的结果。没有输出的算法是无意义),有穷性:有限步骤能完成确定性:每ー步骤必须有确切的定义可行性:能够精确的运行,并且人们可用手动推算的方式也可以达到相同的目的。.算法的复杂度:是算法效率的度量,是评价算法优劣的重要依据。一般用时间复杂度(BIGONOTACTION)和空间复杂度来分析。时间复杂度:a.平均运行时间b.最佳与最差的运行情况时间复杂度指算法花费的时间的复杂度。BIGONOTACTION:N一般表示数据的个数,例:O(logN)表示运算N个数据所需的时间与logN成正比,一般来说复杂度越低效率越高。(用ー个函数运算结果类比算法的复杂情况,统计学的概念)大小排序:O(logN)<O(N)<O(NlogN)<O(NA2)<O(2AN)搜索:线性搜索:O(N) ニ叉搜索:O(logN)排序:冒泡、选择、搜入:O(NA2)快速:O(N*logN).算法检测要件:查找和排序.算法设计的策略:暴力法:穷法所有的可能性。(有限的暴力是可取的,有助理解)递归:最常用,代码又精简(层次太多,有可能出现栈空间用完的情况,所以注意不要出现死循环)分治法:一分为二的思想(哲学)模拟法:模拟实际情况,常用于概率有关的问题贪心算法:米用贪心策略的算法设计优化法:利用生物优先原理。.搜索:二分法:必需是已排好顺序的数据结构,每次一分为二,只要确定一边,另一边就不再纳入搜索范围,故效率特别高。作业:定义ー个自己的结构体单元。定义这种单元数据类型的一个数组。重载这种数据类型的关系运算符(可以元素间直接比较大小)。实现它的二分搜索办法(提示,先排好序,再由中间元间一分为二,后边不断的递归或循环下去直接找到相同或到底)。5.排序:冒泡:比较n-l个相邻数据对,只要这ー轮发生过交换就再进行ー次比较。 (精确)插入:从第二个数据开始,把每个数据插入到合适位置。(插入到左边已经过初步排序的数据) (精确)选择:反复n次,每次在未排序处理的数据中找最小(或最大值) (精确)快速:也是一分为二的分析方法,先找随机分界值,然后把所有数据粗略分为两组。小的组靠左边,大的组靠右边。对两组再进行一分为二处理,再找组中的随机分界值,这样递归下去。(不断在确定分界值的相对位置,直到不能再找到ー个分界值,粗选今精确,可以剔除很多不必要的参与排序的数值)十七、模板模板是泛化编程(GenericProgramming)的基础。它是ー种参数化(Parameterized)的类或函数。这里所说的参数(实参)不单指我们传统函数所说的数值形式的参数,还可以是ー种数据类型。注:泛化编程就是对抽象出来的算法的编程,泛化是指可以广泛的透用于不同的数据类型。.模板格式:普通函数模板:templateく类型或常数形参列表〉〃0是使用模板的重要标志函数返回类型函数名(函数形参列表){…}类模板模板只是修饰性质(跟CONST修饰成员函数没有多大的本质区别),不能替代主体类的性质,我们所说的模板的继承,重载,多态其实还是在讲类的继承,重载形式,多态。templateく类型或常数形参列表〉“template的作用域是下方{)所在区域,其实它跟下方的class还是同一个语句class类名:权限关键字父类名!,...{函数返回类型成员函数名(函数形参列表);};tempiateく类型或常数形参列表〉函数返回类型类名〈类型或常数形参列表〉::成员函数名(函数形参列表){...}C++对模板使用中的规定:a.对对象的定义需要用0明文指定,而函数则只需要用实参隐性指明(即不需要用0)b.模板使用前需先实例化,它的其实就是对象的实例化并加上模板类型或常数形参列表的实参导入。.模板的参数参数部分:templateo是模板的标志,在〇中,是模板的参数部分。参数可以是类型,也可以是数值,可以有多个,里边的类型也可以是不同的。一切都是按需随意加上。参数可以有默认值:默认值的规则与函数的默认值ー样,如果ー个参数有默认值,则其后的每个参数都必须有默认值。参数的作用:参数的名字在整个模板的作用域内有效,类型参数可以作为作用域内变量的类型;数值型参数可以参与计算,就像使用普通常数一样。ー个模板类一旦指定类型和其它模板参数,也就跟ー个没有使用模板的同类型的普通类没有什么两样。模板的函数重载:其实只是某些情况下的特例处理,本质上还是类型普通函数重载。一旦模板参数确定,就会发现一切还是ー样,跟传统的函数没有什么不同。.使用中的关注点:3.!对模板的语法检查是在使用时(实例化模板参数时)进行,而不是像普通的类或函数在被编译器读到的时候进行。引申的有用也是易错的技巧:可以在模板中做一些类似给类的调用指定一些未知的成员函数的假设。3.2模板类的使用时机:模板侧重于对算法的抽象,也就是说如果你在解决一个问题的时候,每ー个步骤都是固定的,跟实际用哪种数据类型关系不大,可以抽象为模板。如果ー类问题中有很多相同的功能操作,但是这些操作对于具体问题,又会有各种细节的不同处理,那就要用类继承或其它方法处理。作业:把数据结构和算法里边的各种类的实现改写为用模板去取代typedef的使用。十八、STL标准模板库模板基于容器(数据结构,包含其他对象的对象),包含有一些共同的算法(搜索,排序),为我们提供了一套可复用的,经过验证的,除过错的,高性能优化过的,免费的C++库,已集成为编译器的一部分。容器、迭代器(5大迭代器,尽量少用下标运算符〈有些容器类不支持,例如list,为免掌握混乱,少用〉,既然用上STL那就多用迭代器。迭代器:定向指针+限定功能く函数》,例流迭代器,插入迭代器。重心:区间迭代器对(起点迭代器(类似数组下标〇位置〉,结束位迭代器〈类似数组下标上限+1位置>»如数组10个元素,那结朿位迭代器就是:数组名+10),容器类的区间构造函数(区间迭代器对〈有两个参数>))、算法(跟容器或迭代器相关的函数,用到的参数绝大部分是用迭代器来配合,而不是下标值)1.容器的存储:1.!直接存储:容器中有一份对象的拷贝。要占用空间,ー个对象不能放入多个容器,不能包含本身。1.2间接存储:容器只保存对象的指针。对对象的存取通过引用ー个指针(迭代器:Iterator,是普通指针附加上具体的不同的函数功能,就能成为不同的迭代器〈升级版的指针>)来处理。2.基本的容器类:string类:可保存或中间增加可变长度的字符串。它是在堆中分配空间,而char[]数组是在栈中分配(长度容易受到最大栈长度的限制)。对string类的操作,如果是添加到最后时,一般不需要分配内存(它预先会保留一些空闲内存),所以性能是最快的。从另ー个角度看也即意味着它可能会占用比较大的内存,如果知道字符串的具体长度,还是多用字符串数组。vector类(矢量,向量):它就是动态数组,它也是在堆中分配内存,元素会连续存放,也有保留内存,如果减少大小内存也不会释放。如果新值大于当前保留内存大小时オ会再分配内存。对末尾元素的操作是最快的,此时一般不需要移动内存,只有保留内存不足时オ要。对中间和开始处元素的操作(添加,删除)需要移动内存所以性能不高(如果元素是结构或类对象,中间还会伴随构造和析构函数的自动调用)〇list类:它是链表,元素也是在堆中存放,每个元素各自放在ー块内存中。它没有空间预留的习惯。list在哪进行添加删除操作都很快,不需要移动内存,不需要对每个元素进行构造和析构的调整。list头部和尾部的访问最快。技巧:如果经常添加删除大的对象元素,那可用!ist如果对象元素不大,构造和析构不复杂,可以用vectorlist<指针〉是性能最低的,这种情况用vectorく指针〉比较好,因为指针没有构造与析构,也不占用很大内存。deque类:双向队列(双端队列)也是在堆中存放元素。每个堆中保存好几个元素〈像数组》,然后堆与堆之间有指针指向く像链表〉,可以理解为是!ist和vector的结合品。技巧:vector是可以快速地在最后添加删除元素,并可以快速的访问任意元素list是可以快速地在所有地方添加删除元素,但是只能快速的访问最开始与最后的元素deque在开始和最后添加元素都一样快,并提供了随机访问方法,可像vectorー样使用口下标运算符访问任意元素,但是随机访问速度比不上vector快,因为它要内部处理堆跳转。另外它也有保留空间,由于deque不要求连续的空间,所以可以保存的元素比vector更大。在前面和后面添加元素时不需要移动其它块的元素,所以性能也很高。map类:映射,相当于字典,把ー个值映射成另ー个值。像字典索引表里一个字对应的页码相关的解析,是ー对ー的关系。multimap类:多重映射,类似map,但关键字可
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 事故安全培训心德课件
- 支气管哮喘康复护理
- 护理临床总带教老师竞聘
- 项目总监年度个人工作总结
- 事业单位a类课件
- 教研员蹲点汇报
- 购房合同文本7篇
- 个人房产销售合同5篇
- 骨科围手术期患者护理制度
- 公司法务课件
- 北美128个护理诊断
- 2025高考英语全国II卷试题分析及备考策略指导课件
- 人口老龄化带来的公共卫生挑战-深度研究
- 全国公开课大赛一等奖小学二年级下册数学新人教版《除法的初步认识-除法》课件
- 2025年度宠物赛事组织与赞助合同4篇
- 内容理解与概括【知识精研】 中考语文一轮复习精讲专练
- 2025年发展对象考试题库附含答案
- 牙科设备供应及后续服务方案
- 物流公司驾驶员管理的规章制度
- 【MOOC】大学物理-电磁学-北京理工大学 中国大学慕课MOOC答案
- 外包服务合作协议
评论
0/150
提交评论