2009-02-09 22 views
80

Kodumun her tarafına dağılmış sihirli kutuları sevmiyorum ... Bu iki sınıf, işlevde olsa bile, temel olarak herhangi bir işlevin bir işlev nesnesine eşlenmesine izin vermek için nasıl çalışır? < (üye yöntemleri "normal" fonksiyonları genellikle gereken kişiler için __cdecl veya __stdcall olan VC altında __thiscall, ama yani hatta farklı arama kuralları ile çalışır boost::bindboost :: function and boost :: bind work

geçerek bir im olarak ayarlanmış tamamen farklı parametre var> C.

+0

Dupe: http://stackoverflow.com/questions/112738/how-does-boost-bind-work-behind-the-scenes-in-general –

+1

gerçekten değil - bu soru bağlama ve işlev hakkında –

+0

Evet ve Bu nedenle hala nasıl harita bağlayabilirsiniz MyClass: DoSomething (std :: dize str, int sayı) artırmak için sorusu ayrılır: işlev bağlamak yoluyla (& MyClass :: DoSomething, örnek, "Merhaba Dünya", _1) –

cevap

94

boost::function ile uyumlu olması operator() ile her şeye izin verir Parametre olarak bağlanacak doğru imza ile ve bağlamanızın sonucu int parametresiyle çağrılabilir, bu nedenle function<void(int)>'a bağlanabilir.

Bu nasıl çalıştığını (bu açıklama std::function için hem geçerlidir):

boost::bind(&klass::member, instance, 0, _1)return_type ve intklass::member imza çıkarılmaktadır bu

struct unspecified_type 
{ 
    ... some members ... 
    return_type operator()(int i) const { return instance->*&klass::member(0, i); 
} 

gibi bir nesne döndürür ve işlev işaretçisi ve bağlı parametre aslında nesnede saklanır, ancak bu önemli değil,

Şimdi, boost::function herhangi bir tür denetimi yapmaz: Şablon parametresinde sağladığınız herhangi bir nesneyi ve imzayı alır ve imzanız gereği çağrılabilen ve nesneyi çağıran bir nesne oluşturur. Bu imkansızsa, derleme hatasıdır.

boost::function aslında bu gibi bir amacıdır:

template <class Sig> 
class function 
{ 
    function_impl<Sig>* f; 
public: 
    return_type operator()(argument_type arg0) const { return (*f)(arg0); } 
}; 

return_type ve argument_typeSig ayıklanır ve f dinamik yığın üzerine tahsis edilir. Farklı boyutlarda olan birbirinden bağımsız nesnelerin boost::function'a bağlanmasına izin vermek gerekiyor.

function_impl sadece soyut bir sınıf

template <class Sig> 
class function_impl 
{ 
public: 
    virtual return_type operator()(argument_type arg0) const=0; 
}; 

tüm çalışır sınıf, boost::function türetilmiş bir somut bir sınıftır.

  1. (tabii ki, o zaman derleme var) bir tür function_impl_concrete<void(int), unspecified_type> başlatır: Eğer durumda demektir boost::function

    template <class Sig, class Object> 
    class function_impl_concrete : public function_impl<Sig> 
    { 
        Object o 
    public: 
        virtual return_type operator()(argument_type arg0) const=0 { return o(arg0); } 
    }; 
    

    atamak nesnenin her türü için bir tane var, atama işlevini artırmak için

  2. :: fonksiyon boost f üyesine bu nesneyi atar yığın
  3. o türde yeni bir nesne oluşturur

İşlev nesnesini çağırdığınızda, uygulama nesnesinin sanal işlevini çağırır; bu, çağrıyı özgün işlevinize yönlendirir.

YASAL UYARI: Bu açıklamadaki isimlerin kasten yapılmış olduğunu unutmayın. Gerçek kişilere veya karakterlere benzerlik ... biliyorsunuz. Amaç ilkeleri açıklamaktı.

+0

, bu nedenle, herhangi bir kombinasyon ve sayıdaki argümana izin vermek için temelde argümanlardan temel olarak oluşturulmuş argümanlardan elde edilen struct unspecified_type (yani operatör() fonksiyonundaki kod) içeriğidir? –

+1

Hayır, tüm nesnelere (ve farklı şablon argümanlarının kombinasyonları ele aldığına) ilişkin işleç şablonları() vardır. – jpalecek

+0

Son kod bloğunda şu okur: 'arg0) const = 0 {return ...' ... Bunu daha önce hiç görmedim. C++ faq'e bağlı bir takip mesajının, saf sanal bir fonksiyonun bir vücuda sahip olabileceğini açıklayan bir forumda, işleyemeyen bir örnek buldum, ancak sözdizimini (clang & gcc) kullanarak derlemek için herhangi bir kod alamıyorum. –