2011-10-28 24 views
6

Stroustrup'un C++ kitabında, bir argüman alarak özel bir manipülatörün bir örneği vardır (lütfen ekli koda bakın). Yapının nasıl oluşturulduğu konusunda kafam karıştı. Özellikle, "smanip" in yapıcısı için, "ff" işlev işaretçisi için biri diğeri "ii" için bir tane olmak üzere iki int argumanı var gibi görünüyor. AyrıcaArgümanlar ile akış manipülatörleri nasıl çalışır?

cout << setprecision(4) << angle; 

, bu işlevler denilen olsun düzen nedir ve nasıl tip argümanları Ch ve Tr belirlenir: Ben int argümanı kullanarak yapısını oluşturmak geçirilir anlamıyorum? Çok teşekkürler.

// manipulator taking arguments 
struct smanip{ 
    iso_base& (*f) (ios_base&, int); 
    int i; 
    smanip(ios_base& (*ff)(ios_base&, int), int ii) : f(ff), i(ii){} 
}; 

template<cladd Ch, class Tr> 
ostream<Ch, Tr>& operator<<(ostream<Ch, Tr>& os, smanip& m){ 
    return m.f(os, m.i); 
} 

ios_base& set_precision(ios_base& s, int n){ 
    return s.setprecision(n); // call the member function 
} 

inline smanip setprecision(int n){ 
    return smanip(set_precision,n); 
} 

// usage: 
cout << setprecision(4) << angle; 
+1

o kodda herhangi bir "işlev nesne" Gerçekten yok:

Yani çizgi çevirir. Çok benzer isimlerle ilgili üç işlev vardır: "set_precision", "setprecision" ve "ios_base :: setprecision".Eğer dikkat etmiyorsanız, onları karıştırmak kolaydır. –

cevap

0

Manipülatör işlevi bir işlev işaretçisi ve arg olarak int alır ve daha sonra kullanmak üzere hem dahili olarak depolar. kurucu imzası okunabilmesi için, bu iki beyanlarında ayrılabilir:

olan
typedef ios_base& (*f_ptr)(ios_base&,int); 
smanip(f_ptr f, int) 

, ilk değişken işlev işaretçisi ve ikinci bir değerdir.

Örnek koddaki yürütme sırasına göre, önce işlev setprecision işlevi çağrılır; bu işlev, işlev işaretçisi ve değeri smanip nesnesinin içine kaydeder ve döndürür. Nesne, argümanı geçen geçerli akıştaki kayıtlı işlev işaretçisini ayıklayıp yürüten uygun operator<<'a geçirilir.

// on the calling end 
     setprecision(4) // --> construct __s = smanip(set_precision, 4) 
(cout <<    ) // --> passes __s to `operator<<` 
// inside operator<< 
return m.f(os, m.i); // calls: set_precision(os, 4) (m.f == &set_precision 
          //        m.i == 4) 
6
setprecision(4) 

aramalar

set_precision işlev işaretçisi bir smanip oluşturur
inline smanip setprecision(int n){ 
    return smanip(set_precision,n); 
} 

ve n.

struct smanip{ 
    ios_base& (*f) (ios_base&, int); 
    int i; 
    smanip(ios_base& (*ff)(ios_base&, int), int ii) : f(ff), i(ii){} 
}; 

smanip

bir işlev için bir işaretçi ve bir tam sayıyı tutan bir yapıdır. Bu işlev, bir ios_base referansı ve bir int alır ve ios_base başvuruyla döndürür. Bu şablonu maçları

smanip m(&setprecision, 4); 
cout << m << (otherstuff); 

:

Bu noktada hat böyle etkili bir şekilde olduğunu

template<class Ch, class Tr> 
ostream<Ch, Tr>& operator<<(ostream<Ch, Tr>& os, smanip& m){ 
    return m.f(os, m.i); 
} 

Ve derleyici sol tarafta dereden Ch ve Tr edinebilirim. Bu durumda, std::cout. Kod, m.f(os, m.i)'u çalıştırır. Bu, smanip tarafından tutulan işlev akışını, akışa ve smanip tarafından tutulan tam sayıya iletir.

ios_base& set_precision(ios_base& s, int n){ 
    return s.setprecision(n); // call the member function 
} 

Bu cout.setprecision(n) çağırır.

std::cout.setprecision(4) << angle;