2008-11-05 2 views
3

В C++, когда виртуальная функция может использовать статическое связывание? Если к нему обращаются через указатель, доступ к которому осуществляется напрямую или никогда?В C++, если функция-член является виртуальной, когда можно использовать статическое связывание?

ответ

2

Статическое связывание может быть выполнено только в том случае, если тип объекта полностью недвусмыслен во время компиляции. Я могу только думать о четырех местах, где тип абстрактного объекта недвусмыслен: в конструкторе, в деструкторе, при объявлении локально и в пределах той же области, что и динамическое распределение. Я не очень хорошо знаю этот стандарт, поэтому я не мог сказать, что он говорит об этих четырех возможностях (я бы сказал, что первые два являются статически связанными, третий возможный статически связан и последний нет, хотя, вероятно, он говорит, что он не определен или зависит от реализации). Помимо этих точек объект, к которому осуществляется доступ через указатель базового класса, может указывать на производный класс, а текущая единица перевода не знает, поэтому статическая привязка невозможна. Функция может быть вызвана с указателем на базовый класс в одном экземпляре и указателем на производный класс в другом!

+1

Оптимизатор может вставлять различные области с помощью вставки. Если тип известен в одной из этих областей, он будет известен в плавкой области. – MSalters 2008-11-06 10:52:55

6

Если вы хотите, чтобы вызвать версию базового класса функции, вы можете сделать это, явно называя базовый класс:

class Base 
{ 
public: 
    virtual ~Base() {} 
    virtual void DoIt() { printf("In Base::DoIt()\n"); } 
}; 

class Derived : public Base 
{ 
public: 
    virtual void DoIt() { printf("In Derived::DoIt()\n"); } 
}; 

Base *basePtr = new Derived; 
basePtr->DoIt(); // Calls Derived::DoIt() through virtual function call 
basePtr->Base::DoIt(); // Explicitly calls Base::DoIt() using normal function call 
delete basePtr;
+0

Hah, я был в середине набора почти точно такого же сообщения! Упрекнул вас. – 2008-11-06 00:15:18

7

Когда виртуальный метод вызывается с помощью указателя или ссылки, динамическое связывание используемый. В любое другое время используется привязка времени компиляции. Пример:

class C; 

void Foo(C* a, C& b, C c) { 
    a->foo(); // dynamic 
    b.foo(); // dynamic 
    c.foo(); // static (compile-time) 
}