Когда компилятор может статически связывать вызов виртуальной функции?

Я ожидал, что компилятор сможет статически разрешить вызов функции к виртуальной функции, если тип класса известен во время компиляции (например, если экземпляр класса не используется через ссылку или указатель, как показано ниже в примере 1).

Однако я наблюдал странное поведение компилятора Visual Studio 2010 с C++ и хотел бы знать, не стоит ли компилятору статически не привязывать вызовы к "правильной" виртуальной функции, когда экземпляры классов с виртуальными функциями являются членами структуры, доступ к которой осуществляется по ссылке.

Следует ли ожидать, что компилятор будет статически связывать вызовы к функции f() в примере 2) ниже? Распространяется ли каким-то образом "ссылочное" значение cr. несмотря на то, что 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  
}
13
задан Matthieu M. 3 September 2011 в 10:12
поделиться