Spíš ignorační, ne? Už podle deklarace je jediným účelem téhle funkce se té nechtěné výjimky prostě nějak zbavit.
Takový návrh prostě narazí u té části lidí, kteří vyjímky chytají a neignorují.
a jak to dělají, když v destruktoru vyhodit výjimku nesmějí. Jak jinak to dělají. Jediný co můžete s takovou výjimkou udělat je, že jí vyhodíte, nebo zaignorujete.
No a říct o lidech jako Stroustrup, Alexandrescu a podobných, že jsou to úředníci co neradi myslí ...
Jsou to lidé. Ne bohové. Alexandrescu má spoustu nápadů a některé práce jsem od něj četl a považoval jsem je za skvělé. Jindy mi to přišlo jako blbost a úchylárna. Třeba například jeho alokátor malých objektů byl bezva. Nicméně časem jsem ho vylepšil a začal používat jinak, protože pro jeho globalní řešení jsem nenašel uplatnění.
Stroustrup.... no prostě to je člověk, který programuje úplně jinak než já. Co jsem od něj četl, to byla většinou pěkná prasárna. Tak jsem ho začal ignorovat. Tím ho nechci schazovat, jen mi úplně jeho styl nesedl
A ta vnořená destrukce házet může, nebo ne? Vždyť likviduje úplně to samé, jako ta vnější. Nebo se to, co se nepodaří zrušit, taky prostě odignoruje?
Napadáte příměr. Říkal jsem, že to lze chápat jako uvedení objektu do původního stavu a jeho následující destrukci. Nebo to berte tak, že to je uvedení objektu do stavu, kdy ho lze bezpečně a bez výjimek zdesrtruovat.
Když na tom nesejde, tak ano. Ale když na tom nesejde, tak můžu chyby odignorovat rovnou a nemusím nic házet.
A jak to uvnitř objektu poznáte, že na tom nesejde? A co když na tom sejde? Samozřejmě, že ve wraperu kolem FILE mám mojí oblíbenou konstrukci se std::uncaught_exception(). Nehledě na to, že ten wrapperu už stejně delší dobu nepoužívám.
Takže neuložení souboru je špatně, ale když neprojde flushnutí bufferu a díky tomu ten soubor nepůjde otevřít, tak je to něco jiného? Já v tom žádný principielní rozdíl nevidím. V obou případech je to nespolehlivé.
Záleží, jaké máte zadání. Jak se to bude používat. Pokud píšu objekt řešící streamování, tak nejspíš chci ukrýt nějaké vnitřní bufferování, které má za úkol, že mi optimalizuje zápis. V normální použití mi přijde naprosto nepřijatelné, abych se staral o flushování dat. Někde na to zapomenu a nastane problém. Prostě se streamem se pracuje tak, že buffer je vnitřní záležitost, která se nepřenáší ven. A pokud stream má funkcí flush(), tak se to většinou chápe jako hint (funkce může být prázdná).
U objektu Word který obsahuje dokument je věc odlišná. Dokument je věc veřejná o které se navenek ví. Je dokonce zadané, že ne vždy je uložení objektu chtěné - zatímco u streamu se předpokládá, že nabufferovaná data se vždy uloží, u dokomentu ve wordu to není automatický předpoklad.
A mohl bych pokračovat dál, třeba u transakce se nepředpokládá, že by se automaticky commitovala. To nikdo zpravidla nechce, protože od toho transakce jsou. Člověk je chápe jako sandbox, do kterého si připraví všechny operace a až když to má, tak to commitne. Objekt Word lze stejně podobně chápat. Je to spíš sandbox, než stream.
Dobrý programátor si umí udělat analýzu problému a hned vidí, co je a co není logické a jak by to měl používat. Špatný programátor klade takovéhle otázky, aniž by se nad tím zamyslel.
Jak už jsem psal. Pokud šoupnu flush do destruktoru a budu na to spoléhat, tak program sem tam vyprodukuje binec. Pokud budu házet, tak některé případy chytnu ale některé stejně projdou. Pokud mi na tom nefičí, tak nemusím házet vůbec. Pokud mi na tom záleží, tak mi házení moc nepomůže.
Jestli vám některé případy stejně projdou, tak byste se měl hluboce zamyslet nad tím, k čemu používáte výjimky. Možná je nepoužíváte správně. Výjimky řeší výjimečné situace, zpravidla situace, kdy se operace nezdaří. Program se většinou píše tak, že se předpokládá, že všechny operace se zdaří. A pokud je chyba správnou operací, pak se neřeší výjimkou. Takže špatný předpoklad. Ten flush se provede vždy. Když se provádí uvnitř výjimky a nezdaří se, tak se tedy zaignoruje, protože je vysoká pravděpodobnost, že jde o zavlečenou chybu, tedy že to nezdaření je stejně důsledkem již probíhající výjimky. Vaše "někdy stejně projdou" je akademická diskuze a spíš ukazuje na hluboké nepochopení problematiky.
Představte si, že je ten buffer použitý někde hluboko uvnitř knihovny. Už vidím tu dokumentaci: Pozor, během stack unwindingu někdy nedojde k zápisu celého souboru!
nic takového tam samozřejmě nebude. Viz výše. Výjimky se nesmí používat k normálnímu běhu kódu.
Házející rollback? V jakém stavu je ta transakce, pokud rollback vyhodí chybu? Co v takovém případě vlastně můžu dělat? Na tomhle příkladě smrdí daleko víc, než jen házení z destruktoru.
Představte si kod:
{
{
Transaction trn1(connection);
trn1.neco();
}
{
Transaction trn2(connection);
trn2.neco();
}
}
Pokud vylítne výjimka v destruktoru první transakce, tedy rollback vyhodil výjimku, něco nepěkného se nejspíš stalo se spojením s databází. Pak je dobré ukončit tento blok, než se snažit pokračovat vytvářením druhé transakce. Navíc chybová hláška z první výjimky bude asi znít "connection lost", zatímco druhá výjimka, která velmi pravděpodobně vypadne při vytvoření druhé transakce už může znít "invalid socket". Vyhození výjimky při rollbacku je tedy lepší a bezpečnější řešení.
Nikdy jste neprogramoval databáze? Že se divíte rollbacku házící výjimku.
Někoho kdo ignoruje to, že se STL musí vypořádat se spoustou protichůdných požadavků a díky tomu vypadá tak, jak vypadá? Nebojte, za génia Vás určitě považovat nebudu.
Já jsem neříkal, že jí ignoruju, já jsem říkal, že jí nepoužívám. Jak bych mohl, když mé objekty háží v destruktoru výjimky, nebo když používam custom alokátory (které STL neumí - i když vám kdejaký jouda bude tvrdit, že ano). Používám vlastní streamy (zkuste někdy napsat vlastní verzi std::iostream.... dlouhe zimní večery už jsou minulostí). Takže neignoruju, jen nepoužívám. V mých knihovnách není problém STL používat, ale zpravidla se ukáže, že je to k ničemu.