翻出当年的C++笔记,好像挺有意思的样子
C++概述: 1 // 只到末尾 /* */ 注释 2 #include<iostream> using namespace std头文件 #include<iostream.h>就不用了 3 在iostream中 cin>>a>>b; cout<<a<<”hello world”<<endl; end换行符 4 面向对象:包括类的声明,类的使用 5 cout<<hex<<a<<’ ‘<<dec<<b<<endl; dec十进制hex十六进制oct八进制 6 结构名struct 联合名union 枚举名enum定义变量时可省略 7 const 8 函数调用的位置在函数定义之前,需声明。 返回值类型 函数名(参数表);参数表可有 类型 9 主函数运行正常return 0;否则系统会返回负一。 10 内联函数(代替宏定义)定义声明时其中一处加inline 运行时代码完全替换。(代码小, 简单,否则自动变普通函数) 普通函数单独放,都调用这一个 11 带有默认参数的构造函数int special(int x=5,y=10);调用不赋初值则用默认值。 12 一个变量全局和局部都定义了,优先局部,变量前加作用域运算符::为全局。 13 联合(共同体) union 联合类型名{int a;double b;}x,y;调用时x.a; 不同成员用同一地址,即不可以同时存在。 14 强制转换double x=(double)y;或double x=double(y);两种方式。 15 动态分配:指针变量名=new 类型;int *p;p=new int;后用delete p;释放 Int *p=new int[10];delete []p;int *p=new int(10);初始化,切记不可对数组初始化。 If(!p){cout<<”失败”<<endl;}分配失败*p为NULL。 16 引用 (主要作为函数参数)int a;int &b=a;a和b同时改变,为同一个变量,除了做函 数参数或返回值类型时,必须定义时就赋初值。不能建立引用数组,不可建立引用的引 用,不可建立引用的指针。用得少:int &index(int);使用引用返回函数值,可将函数放在 赋值运算符的左边。 类和对象: 1 class 类名{};类的声明和c语言结构体差不多,是一种数据类型。 2 private私有(默认为私有,只能被类内使用)protected保护(可以被类内和派生类使用) public公有 用法词后加:冒号 3 类的函数 需在函数内声明 返回值类型 成员函数名(参数表);一在类外定义函数使用 时返回值类型 类名::成员函数名(参数表){}二在类内定义两种情况,都是被作为内 联函数(inline) 4 类的对象定义一可以再类定义后面给出class A{}a,b;,也可以通过类名定义A a,b; 对象访问成员 对象名.数据成员名 对象名.成员函数名(实参表) 指向对象的指针访问成员 函数setpoint() 则*p=a;三者p->setpoint() a.setpoint() (*P).setpoint等价 5 构造函数: 类是一种数据类型,无存储空间,类的声明中所以不能给数据成员赋初值, 构造函数用来赋初值,无返回值类型,名字与类名必须相同,用法:创建对象时自动调用 Complex A(1.1,1.2);Complex *p=new Complex(1.1,1.2); 不写则系统自动生成一个默认构造 函数去开辟存储空间,一旦写了就没默认函数,定义时必须给传参避免出错。自己写构造 函数的时候参数最好赋初值,且在类内(类外不用)。 一般不要同时用构造函数的重载 和有默认参数的构造函数,系统难分辨。成员初始化列表进行初始化(只有构造函数才可 以用这个方法) 构造函数名(参数表):冒号 成员初始化列表法(常用),例:Complex (double r,double i):real(r),imag(i){函数体} const修饰的成员和引用类型的成 员必须用初始化列表 且成员是按照类中声明的顺序初始化,不是初始化列表,所以相互 之间初始化时注意顺序,可以通过参数表不同对构造函数进行重载以完成不同情况赋初 值。 拷贝构造函数:名字与类相同,只有一个参数,类类型的参数,不定义则默认,数据成员 有指针的时候就会发生问题。3种情况会被调用,一用一个对象给另一个对象赋值,二函 数的形参是类的对象(也相当于创建)三函数的返回值是类的对象(也相当于创建) 6 析构函数: 名与类名相同,前加一个波浪号,无参数,无重载,撤销对象自动调用, ~Complex();return后析构时调用。 可以再构造函数中建立动态,析构函数中delete (常见用法)。 7 对象数组对象成员是数组,对象指针对象成员是指针。 8 this指针,每当创建一个对象时,this就指向他,this是当前调用成员函数对象的起始地址 9 string类字符串 头文件 #include<string> string允许两个字符串直接操作s1=s2,s1+s2, s1<s2,之类 10 函数参数,直接传入不会改变对象,通过引用或指针会改变 11 静态成员:为了一个类的多个对象之间的数据共享,static 数据类型 数据成员名;每个 对象操作都会改变这一个,这个数据成员初始化一般在类外进行,不需要加static,对象 创建之前(常主函数前,类后),这个成员属于类,不像普通成员属于对象,可以 类名:: 静态数据成员名 也可以用对象访问,注意,他可以没创建任何对象的时候就被访问, 也分私有公有保护。 静态成员函数:static 返回类型 静态成员函数名(参数表);大体同静态成员一样,一般 主要用来访问静态数据成员(不访问非静态成员,访问要通过对象名),这样达到了多 个对象之间共享数据。 12 友元 多个类相互合作 友元函数 1不属于任何类的非成员函数2另一个类的成员函数 函数内声明关键字friend 例:friend void disp(参数一般为类类型对象,指针,引用); 就可以访问类的数据成员了 另一个类时:friend void Boy::disp(Girl &);类之间相互合作要 提前声明一下未定义的。 友元类 在另一个类中声明 friend 类名 如有XY类,例X中friend Y;则Y的所有函数都 可以访问X的所有成员。 13 类的组合(对象成员) 一个类的对象作为另一个类的数据成员。重点是如何初始化这个 对象成员,有对象成员的构造函数初始化 函数名(形参表):对象成员1(形参表一), 对象成员2(形参表二){构造函数体} 其中成员的形参表在函数名形参中,且不用说数 据类型。 14 常类型 包括 常引用 :const 类型 &引用名;经常用作形参,常引用做形参,则实参不 会更改。例:int a;int &b=a;则b=12;b=b+10;都是错的。 常对象(宏):const 类名 对象名(参数表);或类名 const 对象名(参数表);定义对象时必须初始化,而且不 可通过各种更改。 常数据成员:只能通过构造函数初始化列表进行初始化,以后不可更 改。常成员函数:类型 函数名(参数表)const;在声明和定义时都要加const,调用时 不用,可以和普通成员函数重载,其中普通数据成员和常数据成员可以被普通函数和常 成员函数调用,只是常的不可以更改,但是,如果一个对象被说明为常对象,通过该对 象只能访问常成员函数,不能访问普通成员函数和数据成员。常成员函数也不能更新数 据成员,不能访问普通函数。 派生和继承: 1 已有类为基累(父类),创建的新类叫派生类(子类)。Protected声明只有类内和派生 的类才可以访问。class 派生类名:继承方式 基类名{新增的数据成员和成员函数};例 class Employee:public Person{}; 创建新类的时候,一派生类把积累的所有成员接收过来,除了构造函数和析构函数。二进 行调整,改变访问属性和重定义(在派生类中声明一个名字相同新成员覆盖了基类的,函 数应该让参数也相同否则变成了重载)三增加新成员和函数。注意:基类的私有成员无论 什么方式都不能继承,私有成员即终止了这个成员权限即私有不能再私有。再次强调:构 造函数先调用基类在调用派生类。 2 派生类的构造函数:基类没有显式定义可以不写(取默认),基类显式,派生类必须重新 定义,例:派生类名(参数总表):基类名(参数表){新增成员的初始化} UStudent(int number1,string name1,float score1,stringmajor1) :Student(number1,name1,score1) {major=major1;} 类内定义的时候不用写冒号后面的基类构造函数,类外的时候在写。 当含有对象成员的派生类的构造函数时:派生类名(参数总表):基类名(参数表),对 象成员1(参数表),对象成员二(参数表){普通成员初始化},构造函数调用顺序,基 类然后初始化列表(按照定义顺序),最后函数体内,析构相反。每个派生类只负责其直 接基类初始化。 UStudent(int number1,string name1,float score1,stringmajor1); 派生类的析构函数:由于析构函数不带参数,所以不接受来也无所谓,执行派生类的构造 函数(只负责派生的成员清理)时会自动调用基类的构造函数。 3 重定义后,要访问原来的成员或函数,可以加上 类名:: 例:obj.X::f(); 4 私有函数可以通过建立一个新公有函数访问,例:void printf2(){printf();},像成员的封装一 样。 5 访问声明(个别调整访问属性):基类的保护成员(函数)或公有成员(函数)经过私有 继承想被对象访问(基类私有不可以),可以在派生类保护声明或公有声明中 基类名:: 成员名(函数名);就可以被对象访问了。注意无返回类型,无函数括号,在基类中什么 格式就是什么格式(公有只能公有,保护只能保护)。基类的函数重载,则将对所有函数 起作用。 6 多重继承:一个派生类具有两个或多个基类时,称作多重继承或多基派生。 class 派生类名:继承方式 基类名1,继承方式 基类名2,继承方式 基类名3{新增成员 函数和数据成员} 大部分与单继承类似。 多重继承构造函数:与上面类似 派生类名(参数表):基类名1(参数表),基类名2 (参数表),基类名3(参数表){函数体} 7 虚基类: 当一个基类派生出多个类,这些部分类又派生出同一个类,则这个类会造成数 据成员和成员函数重复,产生二义性,需要引入虚基类。 Class 派生类名:virtual 继承方式 基类名{函数体} 在派生类中加virtual(virtual和继承 方式可以互换位置),基类的孙类只保留一次,同一层中包含虚基类和非虚基类,应该先 调用虚基类的构造函数,在调用非虚基类,最后派生类构造函数。 8 赋值兼容:不同类型数据之间转换赋值(像普通量强制类型转换一样)。 基类对象使用的地方,可以用基类的公有派生类对象代替,但是只能使用基类的成员,公 有派生类的对象可以给基类赋值(公有派生的可以给基类,大缩小),基类指针,引用都 可(基类指针可以指向公有派生对象) 重载: 1 返回值都可,函数名相同,参数个数或类型不同,构成重载 2 函数重载和带默认值函数一起使用时容易发生二义性。 void x(int r=0,int s=0,int t=0) void x(int r) 3 一个变量全局和局部都定义了,优先局部,变量前加作用域运算符::为全局。 4 联合(共同体) union 联合类型名{int a;double b;}x,y;调用时x.a; 不同成员用同一地址,即不可以同时存在。 5 强制转换double x=(double)y;或double x=double(y);两种方式。 多态性: 1 多态性就是不同对象接受相同的消息时,产生不同的行为。(用一个名字定义不同的函数, 函数执行不同但类似的操作,实现同一个函数名调用不同内容函数),一个借口,多种方 法。 2 联编是指一个计算机程序自身彼此关联的过程。在这个联编过程中,需要确定程序中的操 作调用(函数调用)与执行该操作(函数)的代码段之间的映射关系;按照联编所进行的阶段不 同,可分为静态联编和动态联编。静态:编译时(运行前)就决定如何操作,效率高,运 行快。动态:运行时才确定,灵活,易维护。 3 静态联編支持编译时多态性(静态多态性),通过函数重载(包括运算符重载)和模板实 现。 4 动态联編支持运行时多态性(动态多态性),通过虚函数实现。 5 运算符重载,通过创建运算符重载函数实现,可以是1类外定义的普通函数,2类的成员 函数或3友元函数。1用得少,因为成员一般在类外不可访问,23用的比较多。 6 非基本数据类型不能直接运算(例如加减),需定义运算符重载函数 operator运算符(参数){函数体} 例: Complex operator+(Complex a,Complex b) {Complex c; c.数据成员1=a.数据成员1+b.数据成员1; c.数据成员2=a.数据成员2+b.数据成员2; return c; } 7 大多数运算符允许重载,不包括: . .* :: sizeof ?: 五个 并且只可以重载已有的运算符,不可以自创。 重载后的规则用法与之前一样。 8 运算符重载函数参数至少有一个是类类型(对象,引用,指针)。 9 运算符重载函数参数不可以全是已经有的类型,否则就完蛋了。 10 非标准类型的运算一般都需要进行重载(除了=,因为拷贝函数) 11 友元运算符重载函数 friend 函数类型 operator运算符(形参){函数体} 和之前友元函数知识点基本类似, 12 双目运算符有两个操作数(入口参数),单目运算符有一个操作数。 13 成员运算符重载函数:单目,参数表为空,双目参数表一个,会通过this指针隐式传递 一个。 Complex operator+(Complex a) {Complex c; c.数据成员1=数据成员1+a.数据成员1; c.数据成员2=数据成员2+a.数据成员2; return c; }数据成员为类内定义的成员(this传)。 14 成员运算符重载函数和友元运算符重载函数。有时候必须使用友元,两个操作数类型不 同时,需要写两个友元函数相互重载去重载运算符,成员运算符调换顺序时就会出错。 建议:单目用成员。双目用友元。 15 ++ --运算符重载(本身有两种情况),通过在()内插入int来区分,一般传入0, 前缀方式普通的,后缀方式 双目operator++(X &a,int); 单目operator++(int); 16 赋值运算符=重载,不定义系统会默认生成一个,但是动态分配指针的时候就会有问题, 指向同一地址,析构失败,需要自己写函数,且不可以写成友元函数(顺序不可反) 17 []重载 X[Y] 是一个双目运算符,返回类型 类名 ::operator(形参){函数体} 其中 返回类型 &类名 ::operator(形参){函数体} 通过返回引用,可以使其在赋值的 左边。 18 类型转换:隐式类型转换,int x=5,y;y=3.5+x;分两步(右边一步,等号一步)。级别低的 转换成级别高的。显式转换:常用 类型名(表达式) 不常用 (类型名)表达式。 19 类类型与系统预定义类型转换:1转换构造函数(预定义转换成这个类)2类型转换函数 转换构造函数: 是构造函数,在需要预定义型转换类类型时(可与双目运算符结合以完 成类类型与预定义类型运算), 类名(待转换类型数据){转换函数体} Complex(double r){real=r;imag=0;} 只有一个参数,将预定义转换成类类型,。 (类类型相互转换不介绍) 类型转换函数: 将一个类的对象转换为预定义类型(或其他),只能定义为成员函数, 不可以友元函数,可以类外定义,可以定义多个不同类型的函数。 operator 目标类型(){} operator double(){return real;} 函数前无返回类型,且括号内无参数,必须有返回类型,且返回类型即目标类型,调用: 显式调用:目标类型(要转换的类的对象);隐式调用:不同类型运算操作如果有函数 则自动转换(同预定义隐式相似)。 20 虚函数:基类指针对象可以指向公有派生对象,但是只能访问基类中继承来的成员(之 前提到过),重定义后也是访问原来的。这是需要将函数声明为虚函数,实现动态调用 的目的(在基类中声明函数关键词virtual,派生类写不写都可以,建议写),达到了运 行时多样性。 虚函数定义:在基类中被关键字virtual说明,并在派生类中被重新定义的函数。建立基 类指针,通过指向不同派生类,达到动态调用。 函数声明的时候要写关键词,类外定义的时候不写。 一个基类中定义了虚函数之后,他的所有派生都默认这个为虚函数。 虚函数必须是成员函数,友元,静态成员函数都不可以。 虚函数可以对象点的方式访问,但是没有体现特性,基类指针体现特性。 当基类定义动态指针时,释放时只调用基类的析构函数,可在基类中声明为虚析构函数, 则释放时先调用派生类析构函数,在调用基类的析构函数,实现多态性。 基类中定义为虚析构函数之后,所有派生类析构函数自动定义为虚析构函数。 virtual ~类名(); 如果基类中声明了虚函数,派生类中的必须返回类型也相同,否则会出错。 21 多重继承可以看成多个单继承的组合。 22 虚函数可以作为一个接口,只代表一个抽象的概念,可引入纯虚函数概念, virtual 函数类型 函数名(参数表)=0; 后面变成=0 如果一个类至少有一个纯虚函数,那么就称这个为抽象类。 抽象类只能作为基类,不可以建立对象、不能做参数类型、返回类型、显式转换,但可 以声明建立指向抽象类的指针变量去指向派生类,实现多态性。 如果派生类中没重定义这个纯虚函数,则这个派生类还是一个抽象类。 建一个派生类就可以实现功能达到程序的扩充。 模板与异常处理: 1 模板是实现代码重用机制的一种工具,实现类型参数化 2 分为函数模板和类模板,分别允许用户构造模板函数和模板类 3 函数模板 template<typename 类型参数> //typename 也可写成class 返回类型 函数名(模板形参表) {函数体} template<typename T> T max(T x,Ty) {return x+y;} 使用时T必须实例化(模板实参)为模板函数,T是一个类型。 4 在函数模板中可以使用多个类型参数,template<typename T,typename S> 5 template定义的和函数之间不可以有别的语句 6 模板类似于函数体执行一样的重载函数,函数模板可以和普通的函数进行重载,执行时先 找普通的再找函数模板。 7 类模板和模板类:template<typename T> class 类名{函数体} 使用时:类名<实际类型名>对象名(实参);Compare<int>com(1.1,1.2); 类模板类外定义时: 1需要在每一个成员函数定义前声明多次写template<typename T> 2函数之前也要 类名<类型参数>:: (Compare<T>::函数名(参数){} 8 类模板和函数模板:一个只在函数中单独设置模板,一个在类中都可以用这个模板。 9 异常处理:程序在运行过程中出现的错误叫做异常。 10 一个函数出现异常,逐层向上级调用函数解决,最高级无法处理则自动调用terminate。 似的处理机制分离,底层函数着重解决实际任务。 11三个机制 检查try 抛出throw 捕获catch throw 表达式;抛出一个表达式类型的异常。 try{被检查的语句} catch(异常类型1){} catch(异常类型2){}等等。throw在try中, throw后面可以直接加;表示异常返回。catch(···)表示捕捉任何形式的异常。 如果抛出了一个异常没有捕获,则系统调用terminate终止程序。 C++的流类库与输入输出