hh 现在就不贴代码了 太长了
就贴点文字和图片
c++难的点估计就是概念 内存模型哪些太多了。。。
1.函数易混淆概念
概念区分
-函数重载
-函数覆盖
-函数隐藏
函数重载
-1.同作用域
-2.函数名相同,参数列表不同(参数个数,参数顺序,参数类型)
-3.返回值和调用约定 无关 也与virtual无关
-4.成员函数中const也会构成重载,因为普通的成员函数的this指针是指针常量,而有const的是常量指针常量
函数覆盖(多态,虚函数) - 子类中重写的虚函数覆盖虚表中父类的虚函数对应项
-1.函数声明【函数名,参数列表,返回值等】要一致(子类中的函数和父类中的函数)
-2.父类函数要有virtual关键字,子类可以有可以没有
函数隐藏-子类的名字隐藏父类的名字
-1.函数名一样,参数列表,返回值类型,调用约定不做考虑
注意:如果函数声明一样,并且父类有virtual关键字,则构成函数覆盖
2.内存结构分析
-没有虚继承的情况
1.单个类
|*************|
|成员变量1 |
|成员变量2 |
|成员变量... |
|*************|
2.单个类有虚函数
|*************| __vftable |**************|
|虚函数指针 | -----> 虚函数表 |虚函数地址1 |
|成员变量1 | |虚函数地址2 |
|成员变量2 | |虚函数地址... |
|成员变量... | |**************|
|*************|
3.单继承
|*****************|
|父类成员变量1 |
|父类成员变量2 |
|父类成员变量... |
|子类成员变量1 |
|子类成员变量2 |
|子类成员变量... |
|*****************|
4.单继承有虚函数
|*****************| __vftable |**************|
|虚函数指针 | -----> 虚函数表 |虚函数地址1 |
|父类成员变量1 | |虚函数地址2 |
|父类成员变量2 | |虚函数地址... |
|父类成员变量... | |**************|
|子类成员变量1 |
|子类成员变量2 |
|子类成员变量... |
|*****************|
5.多继承
【如果父类没有虚函数,则没有虚表和虚表指针】
|*****************************|
|第一个继承单父类成员变量1 |
|第一个父类成员变量2 |
|第一个父类成员变量... |
|第二个继承单父类成员变量1 |
|第二个父类成员变量2 |
|第二个父类成员变量... |
|............................ |
|子类成员变量1 |
|子类成员变量2 |
|子类成员变量... |
|*****************************|
6.多继承有虚函数
【如果两个父类都有虚函数,如果只有一个父类有虚函数,那么虚函数指针就只有一个,以此类推】
【如果子类重写了父类的虚函数,不会增加多的虚表指针,而是直接把父类虚表对应的项修改】
【如果子类不是重写父类的虚函数,而是自己有虚函数,也是直接对父类的虚表进行修改,一般放在第一个虚表中】
|*****************************| __vftable |**************|
|虚函数指针 | -----> 虚函数表 |虚函数地址1 |
|第一个继承单父类成员变量1 | |虚函数地址2 |
|第一个父类成员变量2 | |虚函数地址... |
|第一个父类成员变量... | __vftable |**************|
|虚函数指针 | -----> 虚函数表 |**************|
|第二个继承单父类成员变量1 | |虚函数地址1 |
|第二个父类成员变量2 | |虚函数地址2 |
|第二个父类成员变量... | |虚函数地址... |
|............................ | ................ |***************|
|子类成员变量1 |
|子类成员变量2 |
|子类成员变量... |
|*****************************|
-有虚继承的情况
1.单虚继承
|*****************| |******************************|
|偏移块指针 | -----> 偏移块 |0x00000000 |
|本类成员变量1 | |对象首地址到虚基类的偏移地址 |
|本类成员变量2 | |******************************|
|本类成员变量... |
|虚基类成员变量1 |
|虚基类成员变量2 |
|虚基类成员变量... |
|*****************|
2.单虚继承有虚函数
【如果子类没有虚函数,或者只对父类的虚函数进行了覆盖】
|*****************| |******************************|
|偏移块指针 | -----> 偏移块 |偏移块地址到虚表指针的距离 |
|本类成员变量1 | |偏移块地址到虚基类的偏移地址 |
|本类成员变量2 | |******************************|
|本类成员变量... | __vftable
|虚表指针 | -----> 虚函数表 |**************|
|虚基类成员变量1 | |虚函数地址1 |
|虚基类成员变量2 | |虚函数地址2 |
|虚基类成员变量... | |虚函数地址... |
|*****************| |**************|
【如果子类有自己的虚函数】
|*****************| |******************************| |**************|
|虚表指针 | -----> 虚函数表 |偏移块地址到虚表指针的距离 | |虚函数地址1 |
|偏移块指针 | -----> 偏移块 |偏移块地址到虚基类的偏移地址 | |虚函数地址2 |
|本类成员变量1 | |******************************| |虚函数地址... |
|本类成员变量2 | |**************|
|本类成员变量... | __vftable
|虚表指针 | -----> 虚函数表 |**************|
|虚基类成员变量1 | | 虚函数地址1 |
|虚基类成员变量2 | | 虚函数地址2 |
|虚基类成员变量... | | 虚函数地址... |
|*****************| |**************|
3.菱形继承
|********************************| |******************************|
|第一个继承的父类的偏移块地址 | -----> 偏移块 |偏移块地址到虚表指针的距离 |
|第一个继承的父类的成员变量1 | |偏移块地址到虚基类的偏移地址 |
|第一个继承的父类的成员变量2 | |******************************|
|第一个继承的父类的成员变量... |
|第二个继承的父类的偏移块地址 | -----> 偏移块 |******************************|
|第二个继承的父类的成员变量1 | |偏移块地址到虚表指针的距离 |
|第二个继承的父类的成员变量2 | |偏移块地址到虚基类的偏移地址 |
|第二个继承的父类的成员变量... | |******************************|
|............................. |
|本类的成员变量1 |
|本类的成员变量2 |
|本类的成员变量.... |
|虚基类成员变量1 |
|虚基类成员变量2 |
|虚基类成员变量... |
|*******************************|
4.菱形继承有虚函数
【子类自己拥有虚函数并不会增加虚表指针,而是直接在虚基类的虚表中进行了修改】
|*******************************| |******************************| |**************|
|第一个继承的父类的虚函数指针 | -----> 虚函数表 |偏移块地址到虚表指针的距离 | |虚函数地址1 |
|第一个继承的父类的偏移块地址 | -----> 偏移块 |偏移块地址到虚基类的偏移地址 | |虚函数地址2 |
|第一个继承的父类的成员变量1 | |******************************| |虚函数地址... |
|第一个继承的父类的成员变量2 | |**************|
|第一个继承的父类的成员变量.. | |******************************| |************ |
|第二个继承的父类的虚函数指针 | -----> 虚函数表 |偏移块地址到虚表指针的距离 | |虚函数地址1 |
|第二个继承的父类的偏移块地址 | -----> 偏移块 |偏移块地址到虚基类的偏移地址 | |虚函数地址2 |
|第二个继承的父类的成员变量1 | |******************************| |虚函数地址... |
|第二个继承的父类的成员变量2 | |**************|
|第二个继承的父类的成员变量... |
|............................. |
|本类的成员变量1 |
|本类的成员变量2 |
|本类的成员变量.... | |**************|
|虚基类的虚函数指针 | -----> 虚函数表 |虚函数地址1 |
|虚基类成员变量1 | |虚函数地址2 |
|虚基类成员变量2 | |虚函数地址... |
|虚基类成员变量... | |**************|
|*******************************|
2.1-没有虚继承的情况
1.单个类
|*************|
|成员变量1 |
|成员变量2 |
|成员变量... |
|*************|
2.单个类有虚函数
|*************| __vftable |**************|
|虚函数指针 | -----> 虚函数表 |虚函数地址1 |
|成员变量1 | |虚函数地址2 |
|成员变量2 | |虚函数地址... |
|成员变量... | |**************|
|*************|
3.单继承
|*****************|
|父类成员变量1 |
|父类成员变量2 |
|父类成员变量... |
|子类成员变量1 |
|子类成员变量2 |
|子类成员变量... |
|*****************|
4.单继承有虚函数
|*****************| __vftable |**************|
|虚函数指针 | -----> 虚函数表 |虚函数地址1 |
|父类成员变量1 | |虚函数地址2 |
|父类成员变量2 | |虚函数地址... |
|父类成员变量... | |**************|
|子类成员变量1 |
|子类成员变量2 |
|子类成员变量... |
|*****************|
5.多继承
【如果父类没有虚函数,则没有虚表和虚表指针】
|*****************************|
|第一个继承单父类成员变量1 |
|第一个父类成员变量2 |
|第一个父类成员变量... |
|第二个继承单父类成员变量1 |
|第二个父类成员变量2 |
|第二个父类成员变量... |
|............................ |
|子类成员变量1 |
|子类成员变量2 |
|子类成员变量... |
|*****************************|
6.多继承有虚函数
【如果两个父类都有虚函数,如果只有一个父类有虚函数,那么虚函数指针就只有一个,以此类推】
【如果子类重写了父类的虚函数,不会增加多的虚表指针,而是直接把父类虚表对应的项修改】
【如果子类不是重写父类的虚函数,而是自己有虚函数,也是直接对父类的虚表进行修改,一般放在第一个虚表中】
|*****************************| __vftable |**************|
|虚函数指针 | -----> 虚函数表 |虚函数地址1 |
|第一个继承单父类成员变量1 | |虚函数地址2 |
|第一个父类成员变量2 | |虚函数地址... |
|第一个父类成员变量... | __vftable |**************|
|虚函数指针 | -----> 虚函数表 |**************|
|第二个继承单父类成员变量1 | |虚函数地址1 |
|第二个父类成员变量2 | |虚函数地址2 |
|第二个父类成员变量... | |虚函数地址... |
|............................ | ................ |***************|
|子类成员变量1 |
|子类成员变量2 |
|子类成员变量... |
|*****************************|
2.2-有虚继承的情况
1.单虚继承
|*****************| |******************************|
|偏移块指针 | -----> 偏移块 |偏移块地址到虚表指针的距离 |
|本类成员变量1 | |对象首地址到虚基类的偏移地址 |
|本类成员变量2 | |******************************|
|本类成员变量... |
|虚基类成员变量1 |
|虚基类成员变量2 |
|虚基类成员变量... |
|*****************|
2.单虚继承有虚函数
【如果子类没有虚函数,或者只对父类的虚函数进行了覆盖】
|*****************| |******************************|
|偏移块指针 | -----> 偏移块 |偏移块地址到虚表指针的距离 |
|本类成员变量1 | |偏移块地址到虚基类的偏移地址 |
|本类成员变量2 | |******************************|
|本类成员变量... | __vftable
|虚表指针 | -----> 虚函数表 |**************|
|虚基类成员变量1 | |虚函数地址1 |
|虚基类成员变量2 | |虚函数地址2 |
|虚基类成员变量... | |虚函数地址... |
|*****************| |**************|
【如果子类有自己的虚函数】
|*****************| |******************************| |**************|
|虚表指针 | -----> 虚函数表 |偏移块地址到虚表指针的距离 | |虚函数地址1 |
|偏移块指针 | -----> 偏移块 |偏移块地址到虚基类的偏移地址 | |虚函数地址2 |
|本类成员变量1 | |******************************| |虚函数地址... |
|本类成员变量2 | |**************|
|本类成员变量... | __vftable
|虚表指针 | -----> 虚函数表 |**************|
|虚基类成员变量1 | | 虚函数地址1 |
|虚基类成员变量2 | | 虚函数地址2 |
|虚基类成员变量... | | 虚函数地址... |
|*****************| |**************|
3.菱形继承
|********************************| |******************************|
|第一个继承的父类的偏移块地址 | -----> 偏移块 |偏移块地址到虚表指针的距离 |
|第一个继承的父类的成员变量1 | |偏移块地址到虚基类的偏移地址 |
|第一个继承的父类的成员变量2 | |******************************|
|第一个继承的父类的成员变量... |
|第二个继承的父类的偏移块地址 | -----> 偏移块 |******************************|
|第二个继承的父类的成员变量1 | |偏移块地址到虚表指针的距离 |
|第二个继承的父类的成员变量2 | |偏移块地址到虚基类的偏移地址 |
|第二个继承的父类的成员变量... | |******************************|
|............................. |
|本类的成员变量1 |
|本类的成员变量2 |
|本类的成员变量.... |
|虚基类成员变量1 |
|虚基类成员变量2 |
|虚基类成员变量... |
|*******************************|
4.菱形继承有虚函数
【子类自己拥有虚函数并不会增加虚表指针,而是直接在虚基类的虚表中进行了修改】
|*******************************| |******************************| |**************|
|第一个继承的父类的虚函数指针 | -----> 虚函数表 |偏移块地址到虚表指针的距离 | |虚函数地址1 |
|第一个继承的父类的偏移块地址 | -----> 偏移块 |偏移块地址到虚基类的偏移地址 | |虚函数地址2 |
|第一个继承的父类的成员变量1 | |******************************| |虚函数地址... |
|第一个继承的父类的成员变量2 | |**************|
|第一个继承的父类的成员变量.. | |******************************| |************ |
|第二个继承的父类的虚函数指针 | -----> 虚函数表 |偏移块地址到虚表指针的距离 | |虚函数地址1 |
|第二个继承的父类的偏移块地址 | -----> 偏移块 |偏移块地址到虚基类的偏移地址 | |虚函数地址2 |
|第二个继承的父类的成员变量1 | |******************************| |虚函数地址... |
|第二个继承的父类的成员变量2 | |**************|
|第二个继承的父类的成员变量... |
|............................. |
|本类的成员变量1 |
|本类的成员变量2 |
|本类的成员变量.... | |**************|
|虚基类的虚函数指针 | -----> 虚函数表 |虚函数地址1 |
|虚基类成员变量1 | |虚函数地址2 |
|虚基类成员变量2 | |虚函数地址... |
|虚基类成员变量... | |**************|
|*******************************|
|