Привязать функцию-член виртуального класса в базовом конструкторе

В приведенном ниже примере показан базовый класс, который связывает виртуальную функцию-член с fn. На gcc 4.8 вызов fn в производном классе вызовет перегруженную функцию вычисления. Кто-нибудь может объяснить, почему это происходит? Является ли этот компилятор поведения независимым?

#include <functional>
#include <iostream>

class Base {
public:
Base(){
fn = std::bind(&Base::calculate,this,1);
}

virtual int calculate(int value){
return value + 1;
}

std::function<int(int)> fn;
};

class Derived : public Base {
public:
Derived() : Base() {}

int calculate(int value){
return 0;
}
};

int main(int argc, const char **argv){
Derived test;
std::cout << test.fn(10) << std::endl;
/* Output of test.fn(10) is zero, so overloaded function was called */
return 0;
}

1

Решение

Код ведет себя так, как и ожидалось: вызов виртуальной функции-члена отправляет наиболее переопределенной функции в наиболее производном объекте, который содержит объект экземпляра вызова. Тот факт, что вы используете указатель на функцию-член (внутри выражения привязки), не имеет значения; на самом деле, весь смысл функции указателей на члены состоит в том, что они корректно работают с виртуальной диспетчеризацией.

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

Base() : fn([this]() { return this->Base::calculate(1); }) {}
2

Другие решения