此贴用来记录学习C++语言的联想!
学习内容:
1、C++ 的三大特性
答:继承 封装 多态
2 、从继承出发思考
C++ 提供的一种比直接修改代码更好的方式来扩展和修改已经存在的类,能从已有的类派生出新的类,派生类继承了原有类的特征和方法,可以实现代码重用。
继承的优点:
1) 代码重用,减少工作量
2)很方便的修改父类
继承的缺点:
1)继承是侵入性的,只要继承就必须拥有父类的所有属性和方法;
2)可能造成子类代码冗余、灵活性降低,因为子类必须拥有父类的属性和方法。
继承的实现有3种
虚继承属于多继承中的特殊例子,如菱形继承是会出现2个共同的部分,此时如果调用基类的内容会有两个基类,不知道调用那个,因此需要虚继承,虚继承使得该虚继承的基类在子类的内存模型里面只会有一个。构建子类的时候有虚继承的时候,子类会生成虚基类表指针指向虚基类,按照声明顺序依次添加进内存的时候,两个父类的虚基类表相同的时候 后边的不在生成,这样就保证了子类模型中只存在一个基类!
3 多态
具有多种形态,方法的行为取决于调用该方法的对象。即调用同一个方法在派生类和基类中行为不同
多态有两种:静多态(编译的过程中实现)和动多态(在运行时期实现)。
静多态主要是:
1通过模板来实现,宏也是实现静多态的一种途径。使用模板,在编译器就可以实现,编译器将调用的函数与模板匹配实现代码替换。
2函数重载:函数名相同,参数类型或个数不完全相同,返回类型一样(返回值不同 参数相同 也无法实现重载)。
动多态:
虚函数的存在,编译器不能知道那个函数被调用,因此需要在运行过程中实现,被称为动多态/动态链接
Q :为什么存在两种多态形式,全部使用动多态可以么?
有些时候不需要虚函数 / 静多态的效率更高/ 动多态需要在运行时跟踪基类指针
动多态是通过继承、虚函数(virtual)、指针来实现。(三者结合起来实现)
常见的有 父类的指针指向子类对象 调用虚函数
内联函数不能是虚函数虚函数是动态的。
内联函数是要被内嵌的,是在编译时候搞的。
4重写,重载,覆盖,重定义:
1重写=覆盖
一般用于子类在继承父类时,重写(覆盖)父类中的方法。但具体实现不同。
重写需要注意:
被重写的函数不能是static的,必须是virtual的
重写函数必须有相同的类型,名称和参数列表
重写函数的访问修饰符可以不同。尽管virtual是private的,派生类中重写改写为public、protect也可以
2 重载overload
overload是重载,一般是在一个类实现若干重载的方法,这些方法的名称相同而参数形式不同。但是不能靠返回类型来判断。
重载需要注意:
位于同一个类中
函数的名字必须相同
形参列表不同
若一个重载版本的函数面前有virtual修饰,则表示他是虚函数,但他也是属于重载的一个版本
不同的构造函数(无参构造、有参构造、拷贝构造)是重载的应用
3 重定义redefining
派生类对基类的成员函数重新定义,即派生类定义了某个函数,该函数的名字与基类中函数名字一样。
重定义也叫做隐藏,子类重定义父类中有相同名称的非虚函数(参数可以不同)。如果一个类,存在和父类相同的函数,那么这个类将会覆盖其父类的方法,除非你在调用的时候,强制转换为父类类型,否则试图对子类和父类做类似重载的调用时不能成功的。
重定义需要注意:
不在同一个作用域(分别位于基类、派生类)
函数的名字必须相同
对函数的返回值、形参列表无要求
若派生类定义该函数与基类的成员函数完全一样(返回值、形参列表均相同),且基类的该函数为virtual,则属于派生类重写基类的虚函数
若重新定义了基类中的一个重载函数,则在派生类中,基类中该名字函数(即其他所有重载版本)都会被自动隐藏,包括同名的虚函数
重载和重写的区别:
(1)范围区别:重写和被重写的函数在不同的类中,重载和被重载的函数在同一类中。
(2)参数区别:重写与被重写的函数参数列表一定相同,重载和被重载的函数参数列表一定不同。
(3)virtual的区别:重写的基类必须要有virtual修饰,重载函数和被重载函数可以被virtual修饰,也可以没有。
5 封装
封装可以隐藏实现细节,使得代码模块化;封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。在面向对象编程上可理解为:把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。