2012-02-19 3 views
1

Пусть:C++ динамическое связывание с перегрузкой

struct A { 
    virtual int foo(const A& a) const { return 1; } 
}; 

struct B : A { 
    virtual int foo(const A& a) const { return 2; } 
    virtual int foo(const B& b) const { return 3; } 
}; 

void testOverloadingBinding(const A& a,const B& b) { 
    cout << a.foo(b); 
} 

int main() { 
    testOverloadingBinding(B(),B()); 
} 

Он печатает 2. Я бы предположить, что это печатает 3, так как this связывание является динамическим, и, насколько я знаю, перегрузкой имеет статическое связывание. Может ли кто-нибудь объяснить, как компилятор решает, какую функцию вызывать здесь?

ответ

4

Это:

virtual int foo(const B& b) const; 

не переопределение для этого:

virtual int foo(const A& a) const; 

Поэтому он никогда не может быть вызван с помощью ссылки на A.

1
virtual int foo(const B& b) const; 

не отменяет ничего, поэтому компилятор выбирает первую функцию. Но, возможно, в будущем у нас будет динамическое разрешение типа, и в этом случае компилятор выберет вторую функцию. Для получения дополнительной информации см. http://www2.research.att.com/~bs/multimethods.pdf

+0

Что заставляет вас думать, что C++ будет поддерживать двойную отправку в будущем? –

+0

@Oli Charlesworth 1 - это упростит посетитель шаблона. 2 - накладные расходы будут выполняться только в случае определения типа виртуального (см. Предложение). 3 - это упростит использование мультиметодов. 4 - это инициатива от Бьярна Страуструпа :) – innochenti

1

Существует только перегрузка, доступная для решения. Объект, который вы вызываете foo, имеет тип A и в A только одна функция foo(const A&) существует. Динамическая диспетчеризация дает функцию в базовом классе. В C++ функция-член идентифицируется по имени и аргументам. Добавление перегрузки в базу, которая не существует в родительском, не будет включать динамическую отправку на нее.