2010-06-27 11 views
8

parametreleri ve bu rastladım:C++ garip sözdizimi ben Boost "Function" sınıfı belgelerine bir göz geçirdiğini

boost::function<float (int x, int y)> f; 

Bu sözdizimi itiraf etmeliyim benim için son derece kafa karıştırıcı. Bu nasıl yasal C++ olabilir?

Başlık altında herhangi bir numara var mı? Bu sözdizimi herhangi bir yerde belgelenmiş mi?

+0

Lütfen her soru için bir soru sorun - sormak için iki sorunuz varsa, iki ayrı soru gönderin. – bdonlan

+0

Doğru, üzgünüm, tekrar yapmayacağım – Dinaiz

+0

Sorunuzu, soruların birini başka bir soruya bölmek için düzenleyebilirsiniz - bunun gibi cevap vermek zordur, çünkü birisi sizin sorularınızın yanıtını yalnızca biliyorsa cevap vermekte isteksiz olurlar. – bdonlan

cevap

9

[Düzenle] Bu, aslında iki soru olan yazarın orijinal, düzenlenmemiş sorusunun bir yanıtıdır.

Bu sözdizimini itiraf etmeliyim, benim için kafa karıştırıcı. Bu nasıl yasal C++ olabilir? :) Başlık altında herhangi bir numara var mı? Bu sözdizimi herhangi bir yerde belgelenmiş mi?

Bu, tamamen yasaldır ve aslında çok karmaşık değildir.

template <class T> 
class C 
{ 
public: 
    T* function_pointer; 
}; 

void fn(int x) 
{ 
    cout << x << endl; 
} 

int main(int argc, char** argv) 
{ 
    C<void (int x)> c; 
    c.function_pointer = &fn; 
    c.function_pointer(123); // outputs x 
} 

O yapıyor olarak temelde aynı şeydir:

typedef void Function(int); 
C<Function> c; 

Bu tür ++ C sadece uygulanabilir değil, (gerçek tip C parametrelenmiştir) C gibi uygulanabilir bu. Buradaki şablon büyüsü, burada İşlev yazımı gibi bir şey alıyor ve geri dönüş değerleri ve argümanlarının türlerini algılayabiliyor. Burada çok uzun olacağını açıklamak ve güçlendirmek :: fonksiyon bu bilgiyi almak için bir çok fonksiyon işlevini meta-şablonları kullanarak desteklemektedir. Bunu öğrenmek için zaman harcamak istiyorsanız, Boost.Type Özellikleri'nde boost :: function_traits ile başlayan destek uygulamasını anlamaya çalışmalısınız. Ancak, genel sorununuzu çözmek istiyorum. Mükemmel kabul edilebilir kodların birkaç satırını basitleştirmek için çok uğraştığınızı düşünüyorum. Komut alt sınıflarınızın argümanlarını, parametrelenmiş alt sınıf kurucularından geçirerek yanlış bir şey yoktur. Tipikçiler ve destek :: işlev benzeri çözümlerin burada dahil edilmesine, dolayısıyla derleme zamanlarının ve kod karmaşıklığının önemli ölçüde artmasına neden olmaya gerçekten değer mi?

sen daha da azaltmak isterseniz, sadece bir herhangi bir komut alt sınıfı yürütmek ve böylece geri alma yığınına eklemek ve edecek işlevi gerçekleştirmek yazma: Gerçekten çalışmakla düşüncemize

typedef boost::shared_ptr<Command> CommandPtr; 

void execute(const CommandPtr& cmd) 
{ 
    cmd->execute(); 
    // add command to undo stack or whatever else you want to do 
} 

// The client can simply write something like this: 
execute(CommandPtr(new CmdAdd(some_value)); 

Daha karmaşık hale getirmek için buna değmez. Destek yazarları, birçok kişi ve derleyici için pek çok kişi tarafından kullanılacak olan boost :: function için son derece genel amaçlı bir çözüm yazmak istedi. Ancak, birleşik bir geri alma sistemindeki farklı imzalara sahip işlevleri çalıştırabilen bir komut sistemini genelleştirmeye çalışmadılar (böylece başlangıçta bitmiş olduktan sonra bile bu komutların durumu korunmalıdır ve geri alıp -Sonraki infazlarda orijinal hal verilerini yeniden belirtmeden bunları geçersiz kılar). Bunun için miras temelli yaklaşımınız büyük ihtimalle en iyi ve en basit olanıdır.

+2

'typedef float (int, int) Komut', söylemekte özür dilerim, yasal C değil. Doğru C kodu' typedef şamandıra Command (int, int) 'olacaktır. "typedef" düzenli bir bildirim alır ve adlandırılmış nesneyi (örneğin, işlev veya değişken) tanımlamak yerine, nesnenin türüne ilişkin adı takma ad olarak kullanır. –

+0

+1 Harika yanıt – fingerprint211b

+0

@Dale Özür dilerim, haklısın ve bu da C++ 'da yasadışı. Bu, C'nin C c ile neyin parametreleneceğini açıklamaya çalışırken aceleci bir hataydı. Bu yazının eşdeğeri: typedef float Command (int, int); C c. Hatayı düzeltmek için düzenledim. – stinky472