目录树ios
1.继承c++
1.1 基类成员在派生类中的访问属性express
1.2继承时致使的二义性安全
1.3 多基继承函数
2.虚函数的多态spa
2.1虚函数的定义3d
2.2派生类中能够根据须要对虚函数进行重定义指针
2.3 虚函数的访问对象
2.4哪些函数不能定义为虚函数blog
2.5虚函数表指针(vptr)和虚基类表指针(bptr)
2.5.1 虚函数表指针vptr
2.5.2含静态变量、虚函数的类的空间计算
2.5.3虚基类表指针
2.5.4 虚拟继承时构造函数的书写
2.5.5虚函数
3.运行时类型识别与显示转换
3.1 typeid
3.2 显式转换
1.继承
若是一个类有多个直接基类,而这些直接基类又有一个共同的基类,则在最底层的派生类中会保留这个间接的共同基类数据成员的多份同名成员。提出虚继承,虚继承时,公共基类在对象模型中只有一份拷贝。
1.1 基类成员在派生类中的访问属性
这里必定要区分清楚派生类对象和派生类中的成员函数对基类的访问时不一样的。
1.2继承时致使的二义性
1)在公有继承下(私有,保护继承时,不能隐式转换)下,派生类的对象/对象指针/对象引用能够赋值给基类的对象/对象指针/对象引用(发生隐式转换)。但基类的对象/对象指针/对象引用不能赋值给派生类的对象/对象指针/对象引用。由于派生类包含了基类的全部信息,而基类缺少派生类中的信息。
2)c++允许把基类的对象指针/对象引用强制转换为(显式)派生类的对象指针/对象引用。
3)一个指向基类的指针能够用来指向该基类公有派生类的任何对象,这是c++实现程序运行时多态性的关键。
1.3 多基继承
当继承基类时,在派生类中就得到了基类全部数据成员的副本,该副本称为子对象。
类mi会包含的的d1的子对象和d2的子对象。若是多个基类中存在同名成员的状况,形成编译器无从判断具体要访问那个基类的成员,则称对基类成员访问的二义性问题。(解决办法:能够加限定符基类)
2.虚函数的多态
多态是面向对象的精髓。能够归纳为一个接口,多种方法。通俗来说,多态是指同一个操做做用于不一样的对象就会产生不一样的响应。多态性分为静态多态和动态多态。其中的函数重载和运算符重载属于静态多态。虚函数属于动态多态性。c++是经过虚函数实现动态多态的。
2.1虚函数的定义
虚函数的定义是在函数原型前加一个关键字virtual便可。
若是一个基类成员定义为虚函数,那么,他在全部派生类中也保持为虚函数,即便在派生类中省略了virtual关键字,也任然是虚函数。
2.2派生类中能够根据须要对虚函数进行重定义,重定义的格式要求:
1)与基类的虚函数有相同的参数个数;
2)与基类的虚函数有相同的参数类型;
3)与基类的虚函数有相同的返回类型。或者与基类的虚函数相同,或者返回指针(引用),而且派生类虚函数所返回的指针(引用)类型是基类中被替换的虚函数所返回的指针(引用)类型的子类型(派生类型)。
2.3 虚函数的访问
虚函数能够经过对象名访问,此时编译器采用的是静态编译。
1)经过对象名访问虚函数时,调用哪一个类的函数取决于定义对象名的类型。对象类型是基类时,就调用基类的函数。对象类型是子类时就调用子类的函数。
2)使用指针访问非虚函数时,编译器根据指针自己的类型决定要访问那个函数,而不是根据指针指向的对象类型。
3)使用指针访问虚函数时,编译器根据指针所指对象的类型决定要访问那个函数,而不是根据指针自己的类型。
4)使用引用访问虚函数,与使用指针访问虚函数类型,不一样的是,引用一经声明,引用变量自己不管如何改变其调用的函数都不会改变,始终指向开始定义时的函数。在必定程序上提升了代码的安全性。(受限制的指针)
总结:
c++中函数调用默认不使用动态绑定,要触发动态绑定需知足两个条件:
a.只用指定为虚函数的成员函数才能进行动态绑定,成员函数默认为非虚函数,非虚函数不能进行动态绑定。
b.必须经过基类类型的引用或指针进行函数调用。
2.4哪些函数不能定义为虚函数
普通函数(类的非成员函数),静态成员函数,构造函数,友员函数。而内联成员函数和赋值操做符重载函数即便声明为虚函数也毫无心义。
2.5虚函数表指针(vptr)和虚基类表指针(bptr)
2.5.1 虚函数表指针vptr
1)每一个类产生一堆指向virtual functions 的指针,放在表格中,这个表格称为虚函数表。
2)每一个对象被添加一个指针,指向相关的virtual table,一般这个指针被称为vptr(虚函数表指针)vptr的设定和重置由每个类的构造函数,析构函数和复制构造函数自动完成。每一个类所关联的type_info信息(用以支持rtti)也由virtual table 指出。一般放在表格的第一个slot处。
2.5.2含静态变量、虚函数的类的空间计算
sizeof应用在类和结构的处理状况是相同的。可是在类中的静态成员不对结构或类的大小产生影响。
2.5.3虚基类表指针
c++支持单一和多重继承。
class iostream:public istream,public ostream{...};
继承关系也能够指定为虚拟(virtual 共享的意思)
class istream :virtual public ios{...};
class ostream :virtual public ios{...}; //菱形继承
在虚拟继承中,基类无论在继承串链中被派生多少次,永远只会存在一个实体。
在虚拟继承基类的之类中,子类会增长某种形式的指针,或者指向虚基类子对象,或者指向一个相关的表格,表格中存放的不是虚基类子对象的地址,就是其偏移量。此指针叫bptr.
2.5.4 虚拟继承时构造函数的书写
从A类直接虚拟派生(B和C)和间接派生(D)的类中,其构造函数的初始化列表中都要列出对基类A构造函数的调用。这种机制保障无论有多少层继承,虚基类的构造函数必须且只能被调用一次。
若在初始化列表中没有显式调用虚基类的构造函数,则将调用虚基类的默认构造函数。若虚基类没有定义默认构造函数,则编译错误。
2.5.5虚函数
在基类中不能给出虚函数有意义的实现,而把它声明为纯虚函数,他的实现留给基类的派生类去作。
a.两种常见的抽象类
凡有纯虚函数 的类叫抽象类(抽象接口),这种类不能声明对象,只是做为基类为派生类服务。除非在派生类中彻底实现基类中的全部纯虚函数,不然,派生类也是抽象类,不能实例化对象。
只定义了protected型构造函数的类也是抽象类。对于一个类,若是只定义了protected构造函数而没有提供public构造函数,不管是外部仍是派生类中都不能建立该类的对象,但能派生出新类,这种能派生出新类,但不能建立本身对象的类叫另一种形式的抽象类。
3.运行时类型识别与显示转换
3.1 typeid
c++经过下面两种操做符提供RTTI
1)typeid 操做符,返回指针或引用所指对象的实际类型。
2)dynamic_cast操做符,将基类类型的指针或引用安全的转换为派生类型的指针或引用。
只有当typeid的操做数是带虚函数的类类型的对象时,才返回动态类型信息。
3.2 显式转换
c++中的显式转换也称强制类型转换。包括static_cast、dynamic_cast、 const_cas、 reinterpret_cast。
在引用命名的强制类型转换操做符以前,显式强制类型转换用圆括号将类型括起来实现。
1) reinterpret_cast
int *ip;
char *pc=(char*) ip;
效果与reinterpret_cast相同。
int *ip;
char *pc=reinterpret_cast<char*> ip;
2) const_cast
除了添加和删除const特性,用const_cast符执行其余任何类型转换都会引发编译错误。
3)static_cast
编译器隐式执行的任何类型转换均可以由static_cast显式完成。
只有当类型之间可隐式转换时(除类层次间的下行转化除外),static_cast的转换才是合法的。不然出错。类层次间的下行转化不能经过隐式转换完成。
使用static_cast完成下行转换(把基类指针或引用转换为子类指针或引用),因为没有动态类型检查,因此不安全。
c++的基本类型的指针之间不含隐式转换(除void*)须要显示转换。故char* 不能隐式转换为int*。
4)dynamic_cast
把expression转换为type类型的对象,type必须是类的指针,类的引用或void*
a.tpye和expression的类型须要一致,都为指针或引用。
与其余转换类型不一样,dynamic_cast 涉及运行时类型检查,而这个运行时类型信息存储在类的虚函数表里,只有定义了虚函数的类才有虚函数表,对没有虚函数表的类在使用时会致使dynamic_cast编译错误。若是绑定到引用或指针的对象的类型不是目标类型,则dynamic_cast失败。若是转换到指针类型的dynamic_cast失败,则dynamic_cast的结果为0.若是转换到dynamic_cast失败,则抛出一个bad_cast类型的异常。dynamic_cast操做符执行两个操做。首先验证请求的转换是否有效,操做符执行的验证是在运行时进行的。
b.dynamic_cast主要用于类层次间的上行转换和下行转换
dynamic_cast运算符能够在执行期决定真正的类型。若是下行转换时安全的(基类的指针或引用执行一个派生类对象)这个运算符会传回转型过的指针。若是downcast不安全,这个运算符会传回空指针(基类的指针或引用没有指向一个派生类对象)
在类间进行上行转换时,dynamic_cast和static_cast的效果同样。
在类间进行下行转换时,dynamic_cast具备类型检查功能,比static_cast更加安全。
在运行dynamic_cast时必须包括多态类型。static_cast则没有这个限制。