C++中的OOP

来源:互联网 发布:linux curl post 请求 编辑:程序博客网 时间:2024/05/16 02:00

OOP

面向对象程序设计基于三个基本的概念:数据抽象、继承、动态绑定。通过使用数据抽象,可以将类的接口和实现分离;使用继承,可以定义类似的类型并对其相似关系建模;使用动态绑定,可以在一定程度上忽略相似类型的区别,而以统一的方式使用它们。

基本概念

继承

继承描述的是类与类之间的关系,使其之间构成一种层次关系。在这种层次关系中,上层的类成为下层类的基类,而下层的类称为上层类的派生类。一个基类负责定义其所有派生类所共有的成员,而派生类可以定义自己的特殊成员。对于基类定义的共有函数成员,如果希望派生类也定义合适自身版本的该共有函数成员,则可以在基类中将该共有函数声明为虚函数,而派生类必须在其内部对所有重新定义的虚函数进行声明。派生类必须通过类派生列表来指明它是从哪个类继承而来。派生列表的形式为:一个冒号后紧跟以逗号分隔的基类列表。

动态绑定

函数运行版本由实参决定,即在运行时选择函数的版本(注意与函数匹配的不同之处!)。在C++语言中,当使用基类的引用或者指针调用一个虚函数时将发生动态绑定。

基类

1)基类的定义方式和其他类的定义方式类似。
2)基类的成员函数分为两种:希望派生类进行覆盖的函数;希望派生类直接继承而不改变的函数。对于前者,常常定义为虚函数。
3)可以定义受保护的成员:允许派生类访问而禁止其他用户访问。每个基类中可以有三种访问控制说明符:private、public、protected。
4)被用作基类的类必须已经被定义。
5)如果一个类不希望被继承,那么可以通过在类名后紧跟关键字final来实现。
6)含有(或者未经覆盖直接继承)纯虚函数的类是抽象基类。抽象基类负责定义接口,而后续其他的类可以覆盖接口。

派生类

1)基类中的访问说明符是控制派生类从基类继承而来的成员是否对派生类可见,派生类可以访问基类的公有成员和受保护成员,不能访问私有成员
2)派生类可以覆盖基类中的虚函数,但不是必须。如果不进行覆盖,那么会继承基类中的版本。可以在形参列表后添加关键字override来显式地表明对该函数进行了覆盖。
3)必要的时候,编译器会隐式地执行派生类到基类的转换。
4)对于继承而来的成员,派生类并不能对其进行初始化,需要使用基类的构造函数来对其进行初始化。首先初始化积累部分,然后按照声明顺序依次初始化派生类的成员。
5)如果基类定义了一个静态成员,则在整个继承体系中只存在该成员的唯一定义。
6)派生类的声明不必包含它的派生列表,只需要包含类名即可。
7)每个派生类都会继承直接基类的所有成员。

基类与派生类的转换
当基类的指针或者引用指向派生类时,完成了派生类到基类的转换,而且也只能以这种方式完成派生类到基类的转换;不存在基类到派生类的转换,即使通过基类的指针或者引用已经指向了派生类。

虚函数

1)必须为每一个虚函数都提供定义,因为编译器也不知道在程序运行的时候会调用哪一个版本的虚函数,所以必须为所有的虚函数提供定义。
2)动态绑定只有当通过指针或者引用调用虚函数是才会发生。虚函数的动态绑定仅在 基类指针或引用绑定派生类对象时发生,直接传值是不会发生动态绑定的,也就是传值后调用的都是基类中的成员函数。
3)一旦一个成员函数被声明为虚函数,则在所有的派生类中都是虚函数,在派生类中无需通过添加关键字virtual来指明。
4)如果需要覆盖某个虚函数,那么形参列表和和返回类型必须与基类中的函数保持一致。但是,如果返回的类型是类本身的指针或者引用时,则返回类型可以不一致。
5)可以使用override 关键字来指明该成员函数是通过覆盖基类中的虚函数而来。
6)如果需要回避动态绑定机制,强制使用虚函数的某个特定版本,可以使用作用域运算符来实现。
7)在一个函数(并非用virtual修饰的虚函数)的函数体部分用 =0 代替即可以将该函数说明为纯虚函数。且不能在类内部为一个 =0的函数提供函数体,但可以在类外进行定义。含有纯虚函数的类是抽象基类,不能创建抽象基类的对象。
8)构造函数和静态函数不能作为虚函数。 
9)当基类虚函数的形参拥有默认实参时,在发生动态绑定时,该形参的默认值也是基类中所给出的默认值而不是派生类中重新给出的默认值,因为缺省参数执行的静态绑定。因此不建议在派生类的改变默认形参的缺省值。
10)派生类的虚函数是可以重载的,如果派生类希望所有重载版本都对它来说是可见的,那么需要覆盖所有的重载函数或者一个也不覆盖,简单的办法是使用using声明语句,类似于其对成员权限提升的用法。

隐藏:如果基类函数和派生类的函数之间函数名相同而形参列表不同,不论是否有关键字vitural,基类的函数将在派生类中被隐藏;如果基类函数与派生类函数的函数名和形参列表相同但基类函数没有关键字,基类函数将在派生类中被隐藏。隐藏的函数执行的静态绑定,也就是说看调用该函数的指针或者引用的类型,而不是其指针或者引用所指向内存上的对象的类型。

访问控制

1)对于受保护成员:
a) 类的用户不可访问,这个类似于私有成员,只能在类的内部使用不能被外部访问; 
b) 可以被派生类的成员和友元访问; 
c) 派生类的成员或者友元只能通过派生类对象来访问基类的受保护成员。

2)某个类对继承而来的成员的访问权限受两个因素的影响:a) 基类中该成员的访问说明符;b)派生列表中的访问说明符。
公有继承(派生访问说明符为public),则基类的成员在派生类中的访问控制与基类的说明符一致;私有继承(派生访问说明符为private),基类的成员在派生类中都是变为私有的;受保护继承(派生访问说明符为protected),则基类中的public成员在派生类中变为受保护的成员。派生类的继承的访问控制是派生类的用户对于继承来的基类部分的访问权限。整个继承过程不存在提升权限的行为,假设public、protected、private的优先级依次递减,那么在基类中的成员访问说明符高于派生类继承说明符的优先级,那么该成员被继承之后只能获得低优先级的权限。对于基类中的private成员,派生类不管怎么继承方式都不存在被通过派生类访问的可能性。

3)对于经过private继承之后的派生类,基类中的public和procted成员在派生类中变为了private,为了改变该类的用户对这些成员的的使用也就是恢复其原有权限,可以使用的方式有
 a)using 语句 using base::variable;
 b)使用访问声明即使用域说明符,base-class::member.

4)友元关系不能被继承,因此基类的友元在访问派生类成员时不具有特殊性。
5)使用struct和class作为类的类型,在默认继承方式上,前者是public继承,后者是preivate继承。





0 0
原创粉丝点击