C++继承的各种模型

本文探讨了C++中的继承模型,特别是涉及到虚函数和菱形继承的情况。当存在虚函数时,子类会重写父类的相应函数,并将虚函数地址存入虚表。虚拟继承旨在解决菱形继承中的数据冗余问题,通过虚基表记录子类对最顶层父类的偏移量。文章列举并分析了不同类型的继承场景,包括只有成员变量、只有虚函数、以及同时包含成员变量和虚函数的菱形继承,提供了Visual Studio 2013下的实现观察。感兴趣的读者可以参考提供的GitHub代码链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先我们需要知道
如果继承中涉及虚函数 ,就会从在虚表,所谓的虚表就是存储虚函数地址的表格。子类继承的话,子类自己的函数会重写所有父类的满足条件的所有函数,其余的虚函数会保存在第一个父类的虚表中。
如果是虚拟继承的话,在菱形继承的条件下,防止的是数据的冗余,最顶层的父类的内容会保存在模型的最底端,他的一级子类会保存一个虚基表,该表存放的是子类对于他的偏移量。
在visual studio2013下,虚表在虚基表的上面。

1.只有成员变量的菱形继承(无虚拟继承)和只有成员变量的菱形虚拟继承(钻石继承)
这里写图片描述
2.只有虚函数的菱形继承(无虚拟继承)
这里写图片描述
3.只有虚函数的菱形虚拟继承(钻石继承)
这里写图片描述
4.既有成员变量,又有虚函数的菱形继承(无虚拟继承)
这里写图片描述
5.既有成员变量,又有虚函数的菱形虚拟继承
这里写图片描述

#include<iostream>
using namespace std;


typedef void(*p) (void);
void print(int** ptr)
{

    int index = 0;
    printf("0x%p\n", ptr);
    for (; ptr[index] != NULL; index++)
    {
        printf("virtual table [%d]:%p-->", index, ptr[index]);
        p fun = (p)(ptr[index]);
        fun();
    }
    cout << endl;
}

void printvirtualbasetable(int* ptr)
{
    cout << ptr << endl;
    //cout << *(ptr) << endl;
    cout << *(ptr+1) << endl;
}

class A
{
public:
    virtual void a1()
    {
        cout << "A::a1()" << endl;
    }
    virtual void a2()
    {
        cout << "A::a2()" << endl;
    }
};

class B :virtual public A
{
public:
    virtual void b1()
    {
        cout << "B::b1()" << endl;
    }
};

class C :virtual public A
{
public:
    virtual void c1()
    {
        cout << "C::c1()" << endl;
    }
};

class D :public B, public C
{
public:
    virtual void a1()
    {
        cout << "D::a1()" << endl;
    }

    virtual void d1()
    {
        cout << "D::d1()" << endl;
    }
};

//class A
//{
//public:
//  int a;
//};
//
//class B:virtual public A
//{
//public:
//  int b;
//};
//
//class C:virtual public A
//{
//public:
//  int c;
//};
//
//class D:public B,public C
//{
//public:
//  int d;
//};
int main()
{
    D d;
    //d.b = 2;
    //d.c = 3;
    //d.d = 4;
    //d.B::a = 5;
    //d.C::a = 6;
    printvirtualbasetable((int*)*((int*)(&d)+1));
    //printvirtualbasetable((int*)*((int*)(&d)+2));
    d.B::a = 5;
    //d.C::a = 6;
    print((int**)*(int**)(&d));
    //print((int**)*(((int**)(&d)) + 1));
    //print((int**)*(((int**)(&d)) + 4));
    //printvirtualbasetable((int*)*((int*)(&d)));
    //printvirtualbasetable((int*)*((int*)(&d) + 1));
    //printvirtualbasetable((int*)*((int*)(&d) + 3));

    cout << sizeof(d) << endl;
    //print((int**)*(int**)(&d));
    //print((int**)*(int**)(((char*)(&d))+12));

    /*int* ptrb = (int*)*((int*)(&d)+1);
    int* ptrc = (int*)*((int*)(&d)+4);
    printvirtualbasetable(ptrb);
    printvirtualbasetable(ptrc);
    int** vptrb = (int**)*(int**)(&d);
    print(vptrb);
    int** vptrc = (int**)*(int**)(((char*)(&d))+12);
    print(vptrc);
    int** vptra = (int**)*(int**)(((char*)(&d)) +28);
    print(vptra);
    cout << *(int*)(((char*)(&d)) + 8) << endl;
    cout << *(int*)(((char*)(&d)) + 24) << endl;
    cout << *(int*)(((char*)(&d)) + 32) << endl;*/

    return 0;
}
//int main()
//{
//  C c;
//  A* ptra = &c;
//  B* ptrb = &c;
//  int** ptr1 = (int**)(*(int**)(ptra));
//  print(ptr1);
//  int** ptr2 = (int**)(*(int**)(ptrb));
//  c.a = 10;
//  c.b = 20;
//  c.c = 30;
//
//
//  int x = (int)*((int**)(&c) + 1);
//  cout << x << endl;
//
//  printf("%p\n", (int**)(((int**)(&c)) + 1));
//  print(ptr2);
//
//  B b;
//  int** ptr1 = (int**)(*(int**)(&b));
//  int** ptr2 = (int**)(*((int**)(&d) + 2));
//  int** ptr3 = (int**)(*((int**)(&d) + 4));
//  int** ptr4 = (int**)(*((int**)(&d) + 3));
//  print(ptr1);
//  print(ptr2);
//  print(ptr3);
//  print(ptr4);
//  d.a = 10;
//  return 0;
//}

//class A{
//public:
//  int a;
//};
//
//class B :virtual public A
//{
//public:
//  int b;
//};
//
//class C :virtual public A
//{
//public:
//  int c;
//};
//
//class D :public B, public C
//{
//public:
//  int d;
//};
//
//int main()
//{
//  D d;
//  d.a=1;
//  d.b=2;
//  d.c=3;
//  d.d=4;
//  printvirtualbasetable((int*)*(int*)(&d));
//  return 0;
//}

github代码下载地址:
https://github.com/q45101218/CppTest/blob/master/Inherit/allinheritance.cpp

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值