1、普通类继承
g++ -fdump-lang-class -c main.cpp # 通过此命令将类的内存布局打印到 main.cpp.001l.class 文件内
#include <cstdio>
class Base {
public:
int base_var = 1;
void fun() {
std::puts("Base::fun");
}
};
class Derived : public Base {
public:
int derived_var = 2;
void fun() {
std::puts("Base::fun");
}
};
int main() {
printf("%d\n", sizeof(Base));
printf("%d\n", sizeof(Derived));
}
上面代码类的内存布局如下:
Class Base
size=4 align=4
base size=4 base align=4
Base (0x0x7f71742dec60) 0
Class Derived
size=8 align=4
base size=8 base align=4
Derived (0x0x7f717418a1a0) 0
Base (0x0x7f71742ded20) 0
2、虚函数类继承
#include <cstdio>
class Base {
public:
int base_var = 1;
virtual void fun() {
std::puts("Base::fun");
}
};
class Derived : public Base {
public:
int derived_var = 2;
void fun() {
std::puts("Base::fun");
}
};
int main() {
printf("%d\n", sizeof(Base));
printf("%d\n", sizeof(Derived));
}
上面代码类的内存布局如下:
Vtable for Base
Base::_ZTV4Base: 3 entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI4Base)
16 (int (*)(...))Base::fun
Class Base
size=16 align=8
base size=12 base align=8
Base (0x0x7f1ed6f6cc60) 0
vptr=((& Base::_ZTV4Base) + 16)
Vtable for Derived
Derived::_ZTV7Derived: 3 entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI7Derived)
16 (int (*)(...))Derived::fun
Class Derived
size=16 align=8
base size=16 base align=8
Derived (0x0x7f1ed6e181a0) 0
vptr=((& Derived::_ZTV7Derived) + 16)
Base (0x0x7f1ed6f6cd20) 0
primary-for Derived (0x0x7f1ed6e181a0)
3、两个虚函数类继承
#include <cstdio>
class Base1 {
public:
int base1_var = 1;
virtual void fun() {
std::puts("Base::fun");
}
};
class Base2 {
public:
int base2_var = 2;
virtual void fun() {
std::puts("Base::fun");
}
};
class Derived : public Base1, public Base2 {
public:
int derived_var = 2;
void fun() {
std::puts("Base::fun");
}
};
int main() {
printf("%d\n", sizeof(Base1));
printf("%d\n", sizeof(Base2));
printf("%d\n", sizeof(Derived));
}
上面代码类的内存布局如下:
Vtable for Base1
Base1::_ZTV5Base1: 3 entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI5Base1)
16 (int (*)(...))Base1::fun
Class Base1
size=16 align=8
base size=12 base align=8
Base1 (0x0x7f8d14563c60) 0
vptr=((& Base1::_ZTV5Base1) + 16)
Vtable for Base2
Base2::_ZTV5Base2: 3 entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI5Base2)
16 (int (*)(...))Base2::fun
Class Base2
size=16 align=8
base size=12 base align=8
Base2 (0x0x7f8d14563d20) 0
vptr=((& Base2::_ZTV5Base2) + 16)
Vtable for Derived
Derived::_ZTV7Derived: 6 entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI7Derived)
16 (int (*)(...))Derived::fun
24 (int (*)(...))-16
32 (int (*)(...))(& _ZTI7Derived)
40 (int (*)(...))Derived::_ZThn16_N7Derived3funEv
Class Derived
size=32 align=8
base size=32 base align=8
Derived (0x0x7f8d145cf000) 0
vptr=((& Derived::_ZTV7Derived) + 16)
Base1 (0x0x7f8d14563de0) 0
primary-for Derived (0x0x7f8d145cf000)
Base2 (0x0x7f8d14563e40) 16
vptr=((& Derived::_ZTV7Derived) + 40)
4、菱形继承
#include <cstdio>
class Base {
public:
int base_var = 1;
virtual void fun() {
std::puts("Base::fun");
}
};
class Base1 : public Base {
public:
int base1_var = 1;
virtual void fun() {
std::puts("Base::fun");
}
};
class Base2 : public Base {
public:
int base2_var = 2;
virtual void fun() {
std::puts("Base::fun");
}
};
class Derived : public Base1, public Base2 {
public:
int derived_var = 2;
void fun() {
std::puts("Base::fun");
}
};
int main() {
printf("%d\n", sizeof(Base));
printf("%d\n", sizeof(Base1));
printf("%d\n", sizeof(Base2));
printf("%d\n", sizeof(Derived));
}
上面代码类的内存布局如下:
Vtable for Base
Base::_ZTV4Base: 3 entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI4Base)
16 (int (*)(...))Base::fun
Class Base
size=16 align=8
base size=12 base align=8
Base (0x0x7f329622fc60) 0
vptr=((& Base::_ZTV4Base) + 16)
Vtable for Base1
Base1::_ZTV5Base1: 3 entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI5Base1)
16 (int (*)(...))Base1::fun
Class Base1
size=16 align=8
base size=16 base align=8
Base1 (0x0x7f32960db1a0) 0
vptr=((& Base1::_ZTV5Base1) + 16)
Base (0x0x7f329622fd20) 0
primary-for Base1 (0x0x7f32960db1a0)
Vtable for Base2
Base2::_ZTV5Base2: 3 entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI5Base2)
16 (int (*)(...))Base2::fun
Class Base2
size=16 align=8
base size=16 base align=8
Base2 (0x0x7f32960db208) 0
vptr=((& Base2::_ZTV5Base2) + 16)
Base (0x0x7f329622fde0) 0
primary-for Base2 (0x0x7f32960db208)
Vtable for Derived
Derived::_ZTV7Derived: 6 entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI7Derived)
16 (int (*)(...))Derived::fun
24 (int (*)(...))-16
32 (int (*)(...))(& _ZTI7Derived)
40 (int (*)(...))Derived::_ZThn16_N7Derived3funEv
Class Derived
size=40 align=8
base size=36 base align=8
Derived (0x0x7f329629c000) 0
vptr=((& Derived::_ZTV7Derived) + 16)
Base1 (0x0x7f32960db270) 0
primary-for Derived (0x0x7f329629c000)
Base (0x0x7f329622fea0) 0
primary-for Base1 (0x0x7f32960db270)
Base2 (0x0x7f32960db2d8) 16
vptr=((& Derived::_ZTV7Derived) + 40)
Base (0x0x7f329622ff00) 16
primary-for Base2 (0x0x7f32960db2d8)
5、菱形虚继承
#include <cstdio>
class Base {
public:
int base_var = 1;
virtual void fun() {
std::puts("Base::fun");
}
};
class Base1 : public virtual Base {
public:
int base1_var = 1;
virtual void fun() {
std::puts("Base::fun");
}
};
class Base2 : public virtual Base {
public:
int base2_var = 2;
virtual void fun() {
std::puts("Base::fun");
}
};
class Derived : public Base1, public Base2 {
public:
int derived_var = 2;
void fun() {
std::puts("Base::fun");
}
};
int main() {
printf("%d\n", sizeof(Base));
printf("%d\n", sizeof(Base1));
printf("%d\n", sizeof(Base2));
printf("%d\n", sizeof(Derived));
}
上面代码类的内存布局如下:
Vtable for Base
Base::_ZTV4Base: 3 entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI4Base)
16 (int (*)(...))Base::fun
Class Base
size=16 align=8
base size=12 base align=8
Base (0x0x7f1d3955fc60) 0
vptr=((& Base::_ZTV4Base) + 16)
Vtable for Base1
Base1::_ZTV5Base1: 8 entries
0 16
8 (int (*)(...))0
16 (int (*)(...))(& _ZTI5Base1)
24 (int (*)(...))Base1::fun
32 18446744073709551600
40 (int (*)(...))-16
48 (int (*)(...))(& _ZTI5Base1)
56 (int (*)(...))Base1::_ZTv0_n24_N5Base13funEv
VTT for Base1
Base1::_ZTT5Base1: 2 entries
0 ((& Base1::_ZTV5Base1) + 24)
8 ((& Base1::_ZTV5Base1) + 56)
Class Base1
size=32 align=8
base size=12 base align=8
Base1 (0x0x7f1d3940b1a0) 0
vptridx=0 vptr=((& Base1::_ZTV5Base1) + 24)
Base (0x0x7f1d3955fd20) 16 virtual
vptridx=8 vbaseoffset=-24 vptr=((& Base1::_ZTV5Base1) + 56)
Vtable for Base2
Base2::_ZTV5Base2: 8 entries
0 16
8 (int (*)(...))0
16 (int (*)(...))(& _ZTI5Base2)
24 (int (*)(...))Base2::fun
32 18446744073709551600
40 (int (*)(...))-16
48 (int (*)(...))(& _ZTI5Base2)
56 (int (*)(...))Base2::_ZTv0_n24_N5Base23funEv
VTT for Base2
Base2::_ZTT5Base2: 2 entries
0 ((& Base2::_ZTV5Base2) + 24)
8 ((& Base2::_ZTV5Base2) + 56)
Class Base2
size=32 align=8
base size=12 base align=8
Base2 (0x0x7f1d3940b2d8) 0
vptridx=0 vptr=((& Base2::_ZTV5Base2) + 24)
Base (0x0x7f1d3955fde0) 16 virtual
vptridx=8 vbaseoffset=-24 vptr=((& Base2::_ZTV5Base2) + 56)
Vtable for Derived
Derived::_ZTV7Derived: 12 entries
0 32
8 (int (*)(...))0
16 (int (*)(...))(& _ZTI7Derived)
24 (int (*)(...))Derived::fun
32 16
40 (int (*)(...))-16
48 (int (*)(...))(& _ZTI7Derived)
56 (int (*)(...))Derived::_ZThn16_N7Derived3funEv
64 18446744073709551584
72 (int (*)(...))-32
80 (int (*)(...))(& _ZTI7Derived)
88 (int (*)(...))Derived::_ZTv0_n24_N7Derived3funEv
Construction vtable for Base1 (0x0x7f1d3940b3a8 instance) in Derived
Derived::_ZTC7Derived0_5Base1: 8 entries
0 32
8 (int (*)(...))0
16 (int (*)(...))(& _ZTI5Base1)
24 (int (*)(...))Base1::fun
32 18446744073709551584
40 (int (*)(...))-32
48 (int (*)(...))(& _ZTI5Base1)
56 (int (*)(...))Base1::_ZTv0_n24_N5Base13funEv
Construction vtable for Base2 (0x0x7f1d3940b410 instance) in Derived
Derived::_ZTC7Derived16_5Base2: 8 entries
0 16
8 (int (*)(...))0
16 (int (*)(...))(& _ZTI5Base2)
24 (int (*)(...))Base2::fun
32 18446744073709551600
40 (int (*)(...))-16
48 (int (*)(...))(& _ZTI5Base2)
56 (int (*)(...))Base2::_ZTv0_n24_N5Base23funEv
VTT for Derived
Derived::_ZTT7Derived: 7 entries
0 ((& Derived::_ZTV7Derived) + 24)
8 ((& Derived::_ZTC7Derived0_5Base1) + 24)
16 ((& Derived::_ZTC7Derived0_5Base1) + 56)
24 ((& Derived::_ZTC7Derived16_5Base2) + 24)
32 ((& Derived::_ZTC7Derived16_5Base2) + 56)
40 ((& Derived::_ZTV7Derived) + 88)
48 ((& Derived::_ZTV7Derived) + 56)
Class Derived
size=48 align=8
base size=32 base align=8
Derived (0x0x7f1d395cf000) 0
vptridx=0 vptr=((& Derived::_ZTV7Derived) + 24)
Base1 (0x0x7f1d3940b3a8) 0
primary-for Derived (0x0x7f1d395cf000)
subvttidx=8
Base (0x0x7f1d3955fea0) 32 virtual
vptridx=40 vbaseoffset=-24 vptr=((& Derived::_ZTV7Derived) + 88)
Base2 (0x0x7f1d3940b410) 16
subvttidx=24 vptridx=48 vptr=((& Derived::_ZTV7Derived) + 56)
Base (0x0x7f1d3955fea0) alternative-path
评论区