2013-01-18 21 views
8

Próbuję użyć std :: bind(), aby utworzyć funkcję, która wywoła wersję klasy podstawowej funkcji wirtualnej zamiast wywoływania wersji klasy pochodnej.Jak użyć funkcji std :: bind() w celu wywołania wersji wirtualnej funkcji klasy podstawowej?

struct Base 
{ 
    virtual void foo() { cout << "Base\n"; } 
}; 

struct Derived : public Base 
{ 
    virtual void foo() { cout << "Derived\n"; } 
}; 

int main(int argc, const char * argv[]) 
{ 
    Base* base = new Derived; 
    auto baseMethodHopefully = std::bind(&Base::foo, base); 
    baseMethodHopefully(); // Want call to Base::foo(), but get call to Derived::foo(). 

    return 0; 
} 

Rozumiem z elsewhere że nie można normalnie nazywamy funkcję bazową w „anty-wirtualną” sposób taki jak ten. Oczywistym wyjątkiem jest wspólny paradygmat:

void Derived::bar() { Base::bar(); } 

Ponieważ ekspresja Base::bar() jest rozpoznawany jako „anty-wirtualny” (w sensie m Nawiązując do) w ramach metody potomnej, jest możliwe, aby wiązać się z Base::bar() w pożądany sposób od w ramach jednej z metod Deriveda w? Na przykład. coś takiego:

void Derived::bar() 
{ 
    auto baseMethod = std::bind(&Base::foo, this); 
    baseMethod(); 
} 

Jeśli tak, jaka jest składnia?

Odpowiedz

14

Cóż, &Base::foo jest wskaźnikiem funkcji członka. I nie ma sposobu, aby użyć wskaźnika funkcji członka, który nie wywołuje wirtualnego nadpisania. Jedyną składnią, która unika nadpisań wirtualnych, jest ta, w której nazwa klasy, nazwa funkcji i lista argumentów są w tym samym wyrażeniu.

Ale jeśli masz std::bind, prawdopodobnie również lambdy, więc może można użyć:

auto baseMethod = [this](){ return Base::foo(); }; 
//... 
baseMethod(); 
+0

słodkie. Działa jak marzenie. Dzięki! – OldPeculier

+0

Przepraszam, nie dostałem tego. Jak możesz funkcjonować członek bez obiektu? – balki

+1

To wyrażenie lambda działa tylko w funkcji składowej 'Base' lub' Derived' (lub innej podklasy 'Base') i przechwytuje' this'. – aschepler

Powiązane problemy