[英]Why can a derived class virtual function call a base class virtual function? How compiler implement?
[英]When can the compiler statically bind a call to a virtual function?
我期望編譯器能夠靜態解析對函數的函數調用,如果類的類型在編譯時是已知的(例如,如果沒有通過引用或指針使用類實例,如案例1中所示)下面)。
但是,我觀察到Visual Studio 2010的C ++編譯器存在奇怪的行為,我想知道當虛擬類的實例時,編譯器是否有任何理由不靜態綁定對“正確”虛函數的調用函數是通過引用訪問的結構中的成員。
我是否希望編譯器在下面的案例2中靜態綁定對f()的調用? cr的“參考”是否會以某種方式傳播到cr.a,即使a
是A
而不是A&
?
struct A
{
virtual void f() ;
virtual ~A() ;
};
struct B : A
{
virtual void f() ;
virtual ~B() ;
};
struct C {
A a ;
B b ;
};
C & GetACRef() ;
void test()
{
// Case 1) The following calls to f() are statically bound i.e.
// f() is called without looking up the virtual function ptr.
C c ;
c.a.f() ;
c.b.f() ;
A a ;
a.f() ;
// Case 2) The following calls to f() go through the dynamic dispatching
// virtual function lookup code. You can check if you generate the .asm
// for this file.
C & cr = GetACRef() ; // Note that C is not polymorphic
cr.a.f() ; // visual C++ 2010 generates call to f using virtual dispatching
cr.b.f() ; // visual C++ 2010 generates call to f using virtual dispatching
}
顯然,編譯器編寫者並不打算解決這種情況。 也許在實際代碼中不值得他們注意。
如果在其他地方定義了GetACRef
,那么C也可能是多態的,這可能會影響優化。
請注意,編譯器並未解決小型測試程序對人類“顯而易見”的每種可能情況。 編譯器的重點是經常在大型實際程序中發生的情況。
我不知道為什么MSVC不會將你的“案例2”場景編譯成直接調用 - 這當然是可能的。 我認為只有微軟才能回答。
請注意,GCC確實執行了您正在尋找的優化(使用MinGW 4.5.1和-O2
進行測試)。
此外,MSVC甚至按以下順序使用vtable調度(為清楚起見 - 我使用/Ox
優化選項):
A a;
A& ar(a);
ar.f();
因此,不需要函數或容器結構來向編譯器添加潛在的混淆層 - 編譯器沒有理由不能將ar.f()
與該序列中的af()
完全相同。 但正如Bo Persson所暗示的那樣,也許這不是一個非常常見的優化方案(或者MS很明顯沒有得到它)。 同樣,只有MS的編譯器開發人員才能回答。
我不確定我會把這種行為歸類為“奇怪” - 這是一個錯過的優化機會。 我不確定這種事情有多常見。 在這種情況下,您是否希望編譯器生成靜態綁定調用? 也許。 但我認為不會發生這種情況並不太令人驚訝。
也許應該在MS Connect上打開一個問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.