Oletetaanpa tuoterek.cpp - ohjelmassa että hinnat haluttaisiinkin tulostaa kahdella desimaalilla:
ostream &tulosta(ostream &os) const { os.precision(2); os.setf(ios::left | ios::showpoint | ios::fixed ); :-( os << setw(20) << nimike << " " << setiosflags(ios::right) << setw(10) << hinta << " " << setw(4) << kpl; return os; } ... ostream &operator<<(ostream &os,const cTuote &tuote) { return tuote.tulosta(os); }
Nyt tietysti voisi olla ohjelmoijalle yllätys, jos hän kutsuisi
cTuote tuote("Volvo|23700|1"); const double pi = 3.14159265; cout.precision(6); cout << pi << '\n'; cout << tuote << '\n'; cout << pi << '\n';
ja jälkimmäinen piin arvo tulostuisikin vain kahdella desimaalilla. Tämän vuoksi pitäisi alkuperäiset tulostusasetukset palauttaa, mikäli niitä muutetaan.
ostream &tulosta(ostream &os) const { long oldf = os.setf(ios::left | ios::showpoint | ios::fixed ); int olddes = os.precision(2); ... tulostusta ... os.precision(olddes); os.flags(oldf); return os; }
Mutta kuka tämän jaksaa tehdä kerrasta toiseen?
Entäpä jos teemmekin luokan cStreamPre ( stream precision ):
ostream &tulosta(ostream &os) const { cStreamPre pre(os,2); ... tulostusta ... return os; }
ja nyt piikin tulee taas pyydetyllä 6:lla desimaalilla molemmilla kerroilla! Miten?
class cStreamPre { ostream &os; ios::fmtflags oldf; int oldp; public: cStreamPre(ostream &aos=cout,int npre=1,long flags=0) : os(aos) { oldf = os.setf(ios::showpoint | ios::fixed | flags); oldp = os.precision(npre); } ~cStreamPre() { os.flags(oldf); os.precision(oldp); } };
Luokan muodostaja tallettaa olion attribuutteihin tulostuksen muotoilun ennen kuin muotoiluja on muutettu. Kun syntyneen olion vaikutusalue lakkaa, eli poistutaan siitä ohjelmalohkosta jossa olio on syntynyt ( auto), kutsutaan olion hajottajaa, joka palauttaa alkuperäiset arvot. Nyt ohjelmoijan tarvitsee vain antaa olion syntyä automaattisesti
cStreamPre pre(os,2);
lohkon alussa. Ja tämähän saadaan vähemmällä kirjoittamisella kuin tarkkuuden muuttaminen normaalisti:
os.precision(2); os.setf(ios::left | ios::showpoint | ios::fixed );
Huomattakoon, että "temppu" toimii vaikka kesken tulostuksen poistuttaisiin ylimääräisellä return--lauseella. Samoin "temppu" toimii, vaikka tulostuksen sisällä kutsuttaisiin toista samalla tavalla toteutettua tulostusta!