1.虚函数
一般类的布局
class A
{
public:
int m_pbl;
protected:
int m_prt;
private:
int m_prv;
public:
voidfun() // 不在堆栈中占空间
{
cout << "It'sfun." << endl;
}
};
1> class A size(12):
1> +---
1> 0 |m_pbl
1> 4 |m_prt
1> 8 |m_prv
1> +---
1.1 单个类
1.1.1 单个虚函数
class A
{
public:
int m_pbl;
protected:
int m_prt;
private:
int m_prv;
public:
void virtual f1()
{
cout << "It'sf1." << endl;
}
};
2> class A size(16):
2> +---
2> 0 | {vfptr} // 虚表指针
2> 4 |m_pbl
2> 8 |m_prt
2> 12 |m_prv
2> +---
2>
2> A::$vftable@:// 虚表
2> | &A_meta
2> | 0
2> 0 |&A::f1
2>
2> A::f1 this adjustor: 0
1.1.2 多个虚函数
class A
{
public:
int m_pbl;
protected:
int m_prt;
private:
int m_prv;
public:
void virtual f1()
{
cout << "It'sf1." << endl;
}
void virtual f2()
{
cout << "It'sf2." << endl;
}
};
1> class A size(16):
1> +---
1> 0 |{vfptr}
1> 4 |m_pbl
1> 8 |m_prt
1> 12 | m_prv
1> +---
1>
1> A::$vftable@: // 同一张表中
1> | &A_meta
1> | 0
1> 0 |&A::f1
1> 1 |&A::f2
1>
1> A::f1 this adjustor: 0
1> A::f2 this adjustor: 0
1.2 继承
1.2.1 不加函数
class B : public A
{
};
1> class B size(16):
1> +---
1> | +--- (baseclass A)
1> 0 | | {vfptr}//同一个指针
1> 4 | |m_pbl
1> 8 | |m_prt
1> 12 | |m_prv
1> | +---
1> +---
1>
1> B::$vftable@: // B的虚表
1> |&B_meta
1> | 0
1> 0 |&A::f1
1> 1 |&A::f2
1.2.2 子类override父类的函数
class B : public A
{
public:
void f1()
{
cout << "It'sf1 in B." << endl;
}
};
1> class B size(16):
1> +---
1> | +--- (base class A)
1> 0 | |{vfptr}
1> 4 | |m_pbl
1> 8 | |m_prt
1> 12 | |m_prv
1> | +---
1> +---
1>
1> B::$vftable@:
1> | &B_meta// B用来标识类
1> | 0
1> 0 | &B::f1 // 变成了B的版本
1> 1 |&A::f2
1>
1> B::f1 this adjustor: 0
1.2.3 子类添加虚函数
class B : public A
{
public:
void f1()
{
cout << "It'sf1 in B." << endl;
}
void virtual f3()
{
cout << "It'sf3." << endl;
}
};
1> class B size(16):
1> +---
1> | +---(base class A)
1> 0 | |{vfptr} //合成一个表
1> 4 | |m_pbl
1> 8 | |m_prt
1> 12 | |m_prv
1> | +---
1> +---
1>
1> B::$vftable@:
1> |&B_meta
1> | 0
1> 0 |&B::f1
1> 1 |&A::f2
1> 2 | &B::f3 // 添加到虚表的尾部,类标识为B
1>
1> B::f1 this adjustor: 0
1> B::f3 this adjustor: 0
1.2.4 多继承
class A
{
private:
int m_data;
public:
void virtual f1()
{
cout << "It'sf1." << endl;
}
};
class B
{
public:
void virtual f1()
{
cout << "It'sf1 in B." << endl;
}
};
class C : public A, public B
{
};
1> class C size(12):
1> +---
1> | +--- (base class A)
1> 0 | |{vfptr}
1> 4 | |m_data
1> | +---
1> | +--- (base class B)
1> 8 | | {vfptr} // 多个指针
1> | +---
1> +---
1>
1> C::$vftable@A@:
1> |&C_meta
1> | 0
1> 0 |&A::f1
1>
1> C::$vftable@B@:
1> | -8
1> 0 |&B::f1
1.3 纯虚函数
1.3.1 只在父类
class A
{
private:
int m_data;
public:
void virtual f1() = 0;
};
1> class A size(8):
1> +---
1> 0 |{vfptr}
1> 4 | m_data
1> +---
1>
1> A::$vftable@:
1> | &A_meta
1> | 0
1> 0 |&A::f1
1>
1> A::f1 this adjustor: 0
子类实现
class B : public A
{
public:
void f1()
{
cout << "It'sf1 in B." << endl;
}
};
1> class B size(8):
1> +---
1> | +--- (base class A)
1> 0 | |{vfptr}
1> 4 | |m_data
1> | +---
1> +---
1>
1> B::$vftable@:
1> | &B_meta
1> | 0
1> 0 | &B::f1
1>
1> B::f1 this adjustor: 0
1.3.2 父类子类都有
class A
{
private:
int m_data;
public:
void virtual f1() = 0;
};
class B : public A
{
public:
void virtual f3() = 0;
};
1> class B size(8):
1> +---
1> | +--- (base class A)
1> 0 | |{vfptr}
1> 4 | |m_data
1> | +---
1> +---
1>
1> B::$vftable@:
1> | &B_meta
1> | 0
1> 0 |&A::f1
1> 1 |&B::f3
1>
1> B::f3 this adjustor: 0
纯虚函数在内存中布局和一般的虚函数一样。
2.虚继承
2.1 虚继承
class A
{
private:
int m_data;
};
class B : virtual public A
{
};
1> class B size(8):
1> +---
1> 0 | {vbptr} // 指针
1> +---
1> +--- (virtual base A)
1> 4 |m_data
1> +---
1>
1> B::$vbtable@:// 虚继承表
1> 0 | 0
1> 1 | 4(Bd(B+0)A)
1>
1>
1> vbi: class offset o.vbptr o.vbte fVtorDisp
1> A 4 0 4 0
2.2 两个父类继承自同一个祖父类
2.2.1 没有用虚继承
class A
{
private:
int m_data;
};
class B : public A
{
};
class C : public A
{
};
class D : public B, public C
{
};
1> class D size(8):
1> +---
1> | +--- (base class B)
1> | | +--- (base class A)
1> 0 | || m_data
1> | | +---
1> | +---
1> | +--- (base class C)
1> | | +--- (base class A)
1> 4 | || m_data // 两个m_data
1> | | +---
1> | +---
1> +---
2.2.2 加上虚继承之后
class A
{
private:
int m_data;
};
class B : virtual public A
{
};
class C : virtual public A
{
};
class D : public B, public C
{
};
1> class D size(12):
1> +---
1> | +--- (base class B)
1> 0 | |{vbptr}
1> | +---
1> | +--- (base class C)
1> 4 | |{vbptr} //添加了两个虚继承的指针
1> | +---
1> +---
1> +--- (virtual base A)
1> 8 | m_data // 只有了一个m_data
1> +---
1>
1> D::$vbtable@B@:
1> 0 | 0
1> 1 | 8(Dd(B+0)A)
1>
1> D::$vbtable@C@:
1> 0 | 0
1> 1 | 4(Dd(C+0)A)
1>
1>
1> vbi: class offset o.vbptr o.vbte fVtorDisp
1> A 8 0 4 0
3.虚函数和虚继承结合
3.1 一般结合
class A
{
private:
int m_data;
public:
void virtual f1()
{
cout << "It'sf1." << endl;
}
};
class B : virtual public A
{
public:
void f1()
{
cout << "It'sf1 in B." << endl;
}
};
1> class B size(12):
1> +---
1> 0 | {vbptr} //虚继承的指针在前
1> +---
1> +--- (virtual base A)
1> 4 | {vfptr} // 虚函数的指针在后
1> 8 |m_data
1> +---
1>
1> B::$vbtable@:
1> 0 | 0
1> 1 | 4(Bd(B+0)A)
1>
1> B::$vftable@:
1> | -4
1> 0 |&B::f1
1>
1> B::f1 this adjustor: 4
1>
1> vbi: class offset o.vbptr o.vbte fVtorDisp
1> A 4 0 4 0
3.2 子类中有虚函数
class A
{
private:
int m_data;
public:
void virtual f1()
{
cout << "It'sf1." << endl;
}
};
class B : virtual public A
{
public:
void virtual f2()
{
cout << "It'sf2." << endl;
}
};
class B size(16):
1> +---
1> 0 | {vfptr}
1> 4 | {vbptr}
1> +---
1> +--- (virtual base A)
1> 8 | {vfptr} // 2个指针
1> 12 |m_data
1> +---
1>
1> B::$vftable@B@:
1> |&B_meta
1> | 0
1> 0 | &B::f2
1>
1> B::$vbtable@:
1> 0 |-4
1> 1 | 4(Bd(B+4)A)
1>
1> B::$vftable@A@:
1> | -8
1> 0 | &A::f1
1>
1> B::f2 this adjustor: 0
1>
1> vbi: class offset o.vbptr o.vbte fVtorDisp
1> A 8 4 4 0
这种情况比较特殊,与不是虚继承的类相比,子类单独添加了一个虚表的指针。
若B对f1重写了,则
class B : virtual public A
{
public:
void f1()
{
cout << "It'sf1 int B." << endl;
}
void virtual f2()
{
cout << "It'sf2." << endl;
}
};
1> class B size(16):
1> +---
1> 0 |{vfptr}
1> 4 |{vbptr}
1> +---
1> +--- (virtual base A)
1> 8 |{vfptr}
1> 12 |m_data
1> +---
1>
1> B::$vftable@B@:
1> | &B_meta
1> | 0
1> 0 |&B::f2
1>
1> B::$vbtable@:
1> 0 |-4
1> 1 | 4(Bd(B+4)A)
1>
1> B::$vftable@A@:
1> | -8
1> 0 | &B::f1 // f1变成了B的版本
1>
1> B::f1 this adjustor: 8
1> B::f2 this adjustor: 0
1>
1> vbi: class offset o.vbptr o.vbte fVtorDisp
1> A 8 4 4 0
3.3 继承的两个父类继承自同一个祖父类
class A
{
private:
int m_data;
public:
void virtual f1()
{
cout << "It'sf1." << endl;
}
};
class B : virtual public A
{
};
class C : virtual public A
{
};
class D : public B, public C
{
};
1> class D size(16):
1> +---
1> | +--- (base class B)
1> 0 | |{vbptr}
1> | +---
1> | +--- (base class C)
1> 4 | |{vbptr} // 不同类的不同
1> | +---
1> +---
1> +--- (virtual base A)
1> 8 | {vfptr} // 只有一个
1> 12 |m_data
1> +---
1>
1> D::$vbtable@B@:
1> 0 | 0
1> 1 | 8(Dd(B+0)A)
1>
1> D::$vbtable@C@:
1> 0 | 0
1> 1 | 4(Dd(C+0)A)
1>
1> D::$vftable@:
1> | -8
1> 0 |&A::f1
1>
1>
1> vbi: class offset o.vbptr o.vbte fVtorDisp
1> A 8 0 4 0
3.4 继承的两个父类继承自同一个祖父类并且都有虚函数
class A
{
private:
int m_data;
public:
void virtual f1()
{
cout << "It'sf1." << endl;
}
};
class B : virtual public A
{
public:
void virtual f2()
{
cout << "It'sf2." << endl;
}
};
class C : virtual public A
{
public:
void virtual f3()
{
cout << "It'sf3." << endl;
}
};
class D : public C, public B
{
public:
void virtual f4()
{
cout << "It'sf4." << endl;
}
};
1> class D size(24):
1> +---
1> | +--- (base class C) // 虚继承C
1> 0 | |{vfptr}
1> 4 | |{vbptr}
1> | +---
1> | +--- (base class B) // 虚继承B
1> 8 | |{vfptr}
1> 12 | |{vbptr}
1> | +---
1> +---
1> +--- (virtual base A)
1> 16 |{vfptr}
1> 20 |m_data
1> +---
1>
1> D::$vftable@C@:
1> | &D_meta
1> | 0
1> 0 |&C::f3
1> 1 | &D::f4 // 非虚继承则不添加虚表指针,虚函数加到第一个虚表中
1>
1> D::$vftable@B@:
1> | -8
1> 0 |&B::f2
1>
1> D::$vbtable@C@:
1> 0 |-4
1> 1 |12 (Dd(C+4)A)
1>
1> D::$vbtable@B@:
1> 0 |-4
1> 1 | 4(Dd(B+4)A)
1>
1> D::$vftable@A@:
1> | -16
1> 0 |&A::f1
1>
1> D::f4 this adjustor: 0
1>
1> vbi: class offset o.vbptr o.vbte fVtorDisp
1> A 16 4 4 0