轉自:http://blog.csdn.net/fantasywm/article/details/7828744
1.虛函數
一般類的佈局
- class A
- {
- public:
- int m_pbl;
- protected:
- int m_prt;
- private:
- int m_prv;
- public:
- voidfun() // 不在堆棧中佔空間
- {
- cout << "It'sfun." << endl;
- }
- };
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;
- }
- };
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;
- }
- };
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
- {
- };
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;
- }
- };
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;
- }
- };
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
- {
- };
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;
- };
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;
- }
- };
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;
- };
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
- {
- };
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
- {
- };
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
- {
- };
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;
- }
- };
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 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;
- }
- };
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
- {
- };
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;
- }
- };
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