设为首页 加入收藏

TOP

虚继承(一)
2023-07-23 13:38:48 】 浏览:105
Tags:

1. 菱形继承

1)概念

? B,C继承自A,D继承自B,C

2)问题

? 一个派生类中保留间接基类的多份同名成员,可能出现命名冲突和冗余数据问题

2. 虚继承

c++代码示例:

#include <stdio.h>
//定义家具类,虚基类,等同于类A 
class Furniture  {
public:
  Furniture() {
    printf("Furniture::Furniture()\n"); 
    price = 0;
  }
  virtual ~Furniture(){                        //家具类的虚析构函数
    printf("Furniture::~Furniture()\n"); 
  }
  virtual int getPrice()  {                    //获取家具价格
    printf("Furniture::getPrice()\n"); 
    return price;
  }; 
protected:
  int price;                                   //家具类的成员变量
};

//定义沙发类,继承自类Furniture,等同于类B 
class Sofa : virtual public Furniture { 
public:
  Sofa() {
    printf("Sofa::Sofa()\n"); 
    price = 1;
    color = 2; 
  }
  virtual ~Sofa()  {                              //沙发类虚析构函数
    printf("Sofa::~Sofa()\n"); 
  }
  virtual int getColor()  {                       //获取沙发颜色
    printf("Sofa::getColor()\n"); 
    return color;
  }
  virtual int sitDown() {                         //沙发可以坐下休息
    return printf("Sofa::sitDown()\n"); 
  }
protected:
  int color;                                      // 沙发类成员变量
};

//定义床类,继承自类Furniture,等同于类C 
class Bed : virtual public Furniture  { 
public:
  Bed()  {
    printf("Bed::Bed()\n"); 
    price = 3;
    length = 4; 
    width = 5; 
  }
  virtual ~Bed(){                                 //床类的虚析构函数
    printf("Bed::~Bed()\n"); 
  }
  virtual int getArea(){                          //获取床面积
    printf("Bed::getArea()\n"); 
    return length * width;
  }
  virtual int sleep(){                            //床可以用来睡觉
    return  printf("Bed::sleep()\n"); 
  }
protected:
  int length; //床类成员变量 
  int width;
};

//子类沙发床的定义,派生自类Sofa和类Bed,等同于类D 
class SofaBed : public Sofa, public Bed { 
public:
  SofaBed()  {
    printf("SofaBed::SofaBed()\n"); 
    height = 6;
  }
  virtual ~SofaBed(){                             //沙发床类的虚析构函数
    printf("SofaBed::~SofaBed()\n"); 
  }
  virtual int sitDown(){                          //沙发可以坐下休息
    return printf("SofaBed::sitDown()\n"); 
  }
  virtual int sleep(){                            //床可以用来睡觉
    return printf("SofaBed::sleep()\n"); 
  }
  virtual int getHeight() {
    printf("SofaBed::getHeight()\n"); 
    return height;
  } 
protected:
  int height;                                     //沙发类的成员变量
};

int main(int argc, char* argv[]) { 
  SofaBed sofabed;
  Furniture *p1 = &sofabed;   //转换成虚基类指针 
  Sofa *p2 = &sofabed;        //转换成父类指针 
  Bed *p3 = &sofabed;         //转换成父类指针 
  printf("%p %p %p\n", p1, p2, p3);
  return 0; 
}

vs_x86汇编标识:

00401000  push    ebp
00401001  mov     ebp, esp
00401003  sub     esp, 40h
00401006  push    1                     ;是否构造虚基类的标志:1构造,0不构造 ①
00401008  lea     ecx, [ebp-40h]        ;传入对象的首地址作为this指针
0040100B  call    sub_4011D0            ;调用构造函数 ②
00401010  lea     eax, [ebp-40h]        ;获取对象的首地址
00401013  test    eax, eax
00401015  jnz     short loc_401020      ;检查代码
00401017  mov     dword ptr [ebp-4], 0
0040101E  jmp     short loc_40102D
00401020  mov     ecx, [ebp-3Ch]        ;取出对象中的Sofa类虚基类偏移表第二项数据
                                        ;即虚基类对象首地址相对于虚基类偏移表的偏移值
00401023  mov     edx, [ecx+4]          ;取出偏移值并存入edx 
00401026  lea     eax, [ebp+edx-3Ch]    ;根据虚基类偏移表,得到虚基类数据的所在地址 ③
0040102A  mov     [ebp-4], eax          ;利用中间变量保存虚基类的首地址
0040102D  mov     ecx, [ebp-4]
00401030  mov     [ebp-14h], ecx        ;p1=&sofabed 
00401033  lea     edx, [ebp-40h]        ;直接转换SofaBed对象的首地址为父类Sofa的指针 ④
00401036  mov     [ebp-10h], edx        ;p2=&sofabed 
00401039  lea     eax, [ebp-40h]        ;获取对象SofaBed的首地址 ⑤
0040103C  test    eax, eax
0040103E  jz      short loc_40104B      ;地址检查
00401040  lea     ecx, [ebp-40h]
00401043  add     ecx, 0Ch              ;获取Bed类对象的首地址
00401046  mov     [ebp-8], ecx          ;利用中间变量保存Bed类对象的首地址
00401049  jmp     short loc_401052
0040104B  mov     dword ptr [ebp-8], 0
00401052  mov     edx, [ebp-8]
00401055  mov     [ebp-0Ch], edx        ;p3=&sofabed
00401058  mov     eax, [ebp-0Ch]
0040105B  push    eax                   ;参数4:p3
0040105C  mov     ecx, [ebp-10h]
0040105F  push    ecx                   ;参数3:p2
00
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C++ STL学习笔记-C++ STL基础 下一篇c++学习笔记——模板和IO(二)

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目