innholdsfortegnelseFAQ for [no.it.programmering.c++]

4.4.2 Hvordan får jeg til finally i C++?

C++ støtter ikke finally (angivelse av kode som skal utføres enten et unntak oppstår eller ikke).

Der det ser ut som om du trenger finally kan du bruke en eller flere av disse teknikkene:

  1. RAII
    Du bør generelt sørge for opprydding gjennom objekt destruktører, som kalles RAII – Resource Acquisition Is Initialization.
     
  2. std::auto_ptr-klassen.
    C++ standardbibliotekets std::auto_ptr kan brukes til helt enkel opprydding.
     
  3. boost::shared_ptr-klassen.
    Boost-bibliotekets boost::shared_ptr kan brukes til mer generell opprydding; du finner Boost-biblioteket på [http://www.boost.org].
     
  4. ScopeGuard-klassen.
    Andrei Alexandrescu og Petri Marginean sin ScopeGuard-klasse kan brukes til opprydding der du ønsker “alt eller intet”; du finner en artikkel om ScopeGuard på [http://www.cuj.com/documents/s=8000/cujcexp1812alexandr/], og kildekode i [ftp://ftp.cuj.com/pub/2000/cujdec2000.zip].
     
  5. Direkte simulering av finally.
    Hvis ingen av teknikkene ovenfor passer har du høyst sannsynlig et designproblem. Rent praktisk kan det være nødvendig å angripe et slikt problem ad teknisk vei heller enn å restrukturere. For eksempel på grunn av tidspress.

Selv om det ikke er noen permanent løsning, absolutt ikke å anbefale, og heller ikke støttet av alle C++ kompilatorer, her er et program som viser hvordan du kan simulere finally:


    #include    <iostream>      // std::cout, std::endl
    #include    <stdexcept>     // std::runtime_error, std::exception

    int answer( bool doFail )
    {
        struct Result{ int value; Result( int v ): value( v ) {} };

        try
        {
            std::cout << "answer() called" << std::endl;
            if( doFail )
            {
                throw std::runtime_error( "You told me to!" );
            }
            throw Result( 42 );     // Must 'throw', not 'return'.
        }
        catch( ... )
        {
            // Finally:
            std::cout << "answer() returning" << std::endl;

            // Exception propagation or normal return.
            try
            {
                throw;
            }
            catch( Result const& aResult )
            {
                return aResult.value;
            }
        }
    }

    int main()
    {
        try
        {
            int const answer1   = answer( false );      // No-throwing.
            std::cout << "Svaret er " << answer1 << "." << std::endl;

            int const answer2   = answer( true );       // Throwing.
            std::cout << "Svaret er " << answer2 << "." << std::endl;
        }
        catch( std::exception const& x )
        {
            std::cerr << "Failed because: " << x.what() << std::endl;
        }
    }

som gir (skal gi) utskriften

    answer() called
    answer() returning
    Svaret er 42.
    answer() called
    answer() returning
    Failed because: You told me to!