现在的位置: 首页 > 综合 > 正文

C++学习总结

2013年06月22日 ⁄ 综合 ⁄ 共 4120字 ⁄ 字号 评论关闭

首先,讲讲const
我是分三个方面进行总结的,1,const常量;2,const指针,3, const在函数申明中的应用
1, const常量
其定义形式为
const type_name val_name;
这里要注意初始化的问题,定义普通的常量时是需要进行初始化的,如果类内的数据成员,不能直接在类内进行初始化,需要在类的构造函数的初始化列表中进行初始化。
还需要说明的一点就是它跟宏定义的区别,const常量有数据类型,而宏常量是没有数据类型,编译器对于前者可以进行类型安全检查,而对后者只是进行简单的字符替换。
2, const修饰指针
如果const位于星号的左侧,则const就是用来修饰指针所指向的内容,即指针指向的是常量,如果const位于星号的右侧,const就是修饰指针本身,指针的指向就是不可以改变的,因此在定义的同时要对它进行初始化
3, const在函数申明中的应用
在一个函数申明中,const可以修饰函数的返回值,或函数的参数,对于成员函数来说,还可以修饰整个函数,这样的函数就是常成员函数,
申明常成员函数的形式为type_name function_name()const;
还需要注意的一点就是在类外定义常成员函数的时候需要带上后面那个const限定符。(主要是与静态成员函数进行区别一下)
修饰函数的形参时可以防止意外的修改,增强程序的健壮性,长成员函数的就是不允许对类内的其他数据成员进行修改,也是增强程序的健壮性。
函数重载
函数的重载依据有这么几个
参数的类型,参数的个数,以及参数的顺序,还有一点就是加了const限定符的函数
匹配时,首先严格匹配,然后进行相容类型转换如char到int之间,最后可以自定义类型转换,
函数默认参数
函数默认参数是从右端开始设置,匹配时是从左端开始匹配
接下来讲讲类吧
关于类的内容就比较多了,
类跟结构体的区别,类中成员默认为private, 而结构体的成员默认为public,类内可以定义函数而结构体中就不可以定义,用我们老师的话来讲,结构体是单纯堆积的数据空间构造的类型,而类不但描述数据空间还描述其操作的自定义类型。
构造函数
其申明形式为
class_name();
这里需要讲讲的就是在继承时实例化一个派生类的对象时,构造函数的执行顺序,首先要激活基类的构造函数,完成对基类中成员的内存空间分配,然后执行构造函数的函数体,这点老师给出的一个比较好理解的解释就是“分配空间等于是盖房子,构造函数的函数体是装修”,然后就是完成对派生类的成员的空间的分配,接着执行派生类的构造函数的函数体。如果没有自定义构造函数时,系统会自动生成默认无参构造函数,如果用户自己定义了构造函数,则系统不再踢狗默认构造函数。这里说一下关于构造函数的初始化列表的问题,当类中含有常量成员和引用型成员时需要用到初始化列表,还有一种情况就是在继承时,如果基类中没有无参构造函数并且有参构造函数没有默认参数时,那么派生类的构造函数即必须要在初始化列表中给出基类的初始化。
析构函数
其申明形式为
~class_name();
析构函数的作用就是将申请的内存空间释放出来,当没有自定义时,系统会提供默认的析构函数。不过需要注意的就是,析构函数不能释放由new申请的堆空间,这部分空间就需要程序员自己释放,如果不释放的话,可能会造成内存泄露。另外还有一点就是在继承的时候,基类的析构函数应该尽量申明为虚函数,理由就是如果一个基类指针指向派生类的话,删除它的时候时就会调用基类的析构函数,而不会调用派生类的析构函数,从而造成内存泄露。
拷贝构造函数
先讲讲拷贝构造的概念,拷贝构造就是在创建对象时,以其他对象为依据来创建对象,我们称这种创建活动为拷贝构造,还是一样,如果没有自定义拷贝构造函数时,系统将提供默认拷贝构造函数,默认拷贝狗仔函数是一种浅拷贝,当类中含有指针成员的时候,默认拷贝构造函数也只是简单的将指针的值复制过来,这样在析构时,就会出现将同一片内存区域释放两次,造成程序出现异常。因此就需要自定义拷贝构造函数,这样的拷贝也称为深拷贝,
拷贝构造函数的申明形式为
class_name(conat class_name& parameter_name);
当然这里形参也可以是class_name * parameter_name;
转换构造函数
转换构造函数是用于类型转换的,这么说吧,有一个类A,和一个B类型的数据,现在要将B类型的数据转换为A类型,那么就要在类A中这样定义一个转换构造函数 A(const B& parameter_name);
说到这里就想说说operator自定义隐式转换
其申明形式是这样的
operator type_name ();所不同的是这个是将该类类型转换为type_name类型的。跟上面那个正好相反,需要注意的一点就是这个是有返回值的,返回值类型就是所要转换的类型
赋值操作符
还是,如果没有自定义赋值操作符,系统会提供默认赋值操作符,但是如果需要在对象之间做深拷贝的话,是需要自定义赋值操作符的,
赋值操作符的申明形式为
class_name& operator=(class_name& parameter_name);
这里申明的是一个返回class_name类型的引用函数,是为了做赋值时的左值
需要注意的一点就是,定义函数体是需要做自赋值检查,理由是,定义赋值操作符是,被赋值的对象已经存在,需要先把被赋值的对象的空间释放,重新进行资源分配,如果是自己赋值给自己的话,那么,就会把这个要赋值的对象毁了,不能完成赋值操作,
静态成员
静态成员是在main函数之前构造,其生命周期相当于全局变量,需要注意的有两点,一个是静态数据成员的初始化,需要在类外进行初始化的,
其形式为 type_name class_name::static_data_name=value;
第二个就是静态成员函数的问题,当其在类外进行定义是,是不需要再加上static关键字的,还有就是其内部没有默认的this指针,故静态成员函数是不可以访问类中的非静态数据成员的。其调用形式为class_name::function_name();类似于全局函数,只不过在前面加上类的作用域

现在来讲讲继承
首先由三种继承方式,分别为public,private, protected三种继承方式,三种继承方式下派生类对基类中成员的继承的权限变化为
public继承下
派生类可以直接访问基类的public成员,以及protected成员,但对外的时候,protected是不允许外界直接访问的,,需要说明的一定就是,基类类型的指针在public继承方式下是可以指向派生类的,这时候凡是派生类对象出现地方都可以用基类来代替,但在其他两种方式下就不可以了。
protected继承
基类的public,和protected成员在派生类的类外都是被看做protected成员
private继承
基类的public和protected都在派生类的类外看做是private成员
这三种继承方式下基类的private成员都在派生类的类外看做private成员
多重继承,就是一个类同时从多个基类中派生
假定有一个基类Base,类A继承类Base,类B也继承类Base,类C同时继承类A和类B这样在类C中就有两份类Base的数据,就会导致访问时不知道究竟访问的是哪个,所以引进了虚拟继承的概念,让类A和类B分别虚拟继承基类Base,这样类C在同时继承类A和类B时就不会产生两份基类Base的数据了,由此引出虚拟继承的概念。
多态
首先如果基类和派生类中都含有相同的成员函数,在public继承的前提下,如果,用一个基类类型的指针指向派生类的话,调用该成员函数时,调用的是基类的那个成员函数,而我们希望它可以根据传来的参数的类型调用相应类型的函数,实现一种多态的效果。这样就要引入虚函数的概念,
其定义形式为virtual type_bame function_name(parameter);
实现多态的办法就是把基类中该函数申明为虚函数,派生类中相应函数可以不需要申明为虚函数,具体是程序运行时维持一张虚函数表,到底怎么样我也不是很清楚,总之就是这样实现了我们想要的功能,这里补充说明一点就是C++语言的多态性分为编译时的多态性和运行时的多态性,编译时的多态性是通过函数重载和模板实现,而运行时的多态性是通过虚函数实现的。
抽象类
关于抽象类的定义就是,在该类中至少有一个纯虚函数的类,需要注意的是抽象类是不可以被直接实例化的,但可以间接实例化,办法就是,实例化其一个非抽象类的派生类,来隐式调用抽象类的构造函数,所以这也说明抽象类的构造函数是有必要的。
补充说明一点就是纯虚函数的概念
其形式是
virtual type_name function_name()=0;
需要在派生类中重新定义该函数,如果派生类不对它进行定义的话,那么派生类也继续是抽象类。

最后讲讲关于异常处理
主要就是讲讲throes,try, catch
只有在try程序的语句段中使用了throw语句,catch程序段才有意义, 而无论有try程序段直接或间接调用的哪一级函数执行了throw语句,都会被catch捕获,并且一旦抛出了异常(执行throw语句),下一条执行的语句就是捕获该异常的的catch语句,所有中间层次的函数,及其定义的变量都将出栈
catch语句块的5方面工作,
1,给出正确工作的提示信息,并且在程序退出之前保存可能会被破坏的数据
2,根据throw语句传来的异常信息进行相应的处理
3.对于处理不了的异常,尽可能将它转变为能够被另一个异常处理程序处理的形式,并抛出该异常
4,重新尝试执行最初的语句
5,如果需要返回一个有效值给主调函数。

1,catch常跟在try后面,数量不限
2,catch包含的数据类型与函数的数据类型作用相同
3,如果抛出的异常在后面找不到与之匹配的catch,则系统默认调用abort()函数,终止程序
4,catch执行完后,程序将执行跟在最后一个catch后面的代码
需要注意的就是catch的类型匹配十分严格,如抛出char类型的,用int型的不能捕捉到。

抱歉!评论已关闭.