jwillis0720
jwillis0720

Reputation: 4477

How to access objects that were initialized in a try statement

I'm new to C++ and was wondering if you could do the following, or if you have a better way.

I have a custom exception class for my database handler: I use this in my main like this:

int main(int argc, char const ** argv){
    try {
        DatabaseHandler DGeneDB = DatabaseHandler("string/to/path");
    }catch(DatabaseHandlerExceptions &msg) {
        std::cerr << "Couldn't open Database" << std::endl;
        std::cerr << msg.what();
        return 1;
    }
    DGeneDB.foo() //Can't access this object since it was initialized in try statement
    return 0;
}

I have a billion things I want to do with the DGeneDB object and don't want to do it all within the try statement. I only want to catch the constructor exception that is thrown during initialization. What should I do to work with the object outside of try? I mean, if it throws the exception, it will return 1 and will stop main() before it gets to the other object.

Upvotes: 8

Views: 1944

Answers (3)

bat_a_toe
bat_a_toe

Reputation: 71

If you have access to C++17 (and your type has a move constructor), you could use std::optional for that:

std::optional<DatabaseHandler> database{};

try {
    database = DatabaseHandler{arguments};
}
catch (const YourExceptionTypeHere &exception) {
    // ...
    return 1;
}

database->foo();

This way you'll still be able to initialize the object in the try block as you wish, without having to modify your constructor or resorting to heap memory allocations (new/unique_ptr).

If the pointer like syntax/nature of std::optional bothers you, you could also move the object out of the std::optional after you initialize it:

DatabaseHandler real_database{std::move(*database)};

real_database.foo();

Upvotes: 0

Matteo Lucarelli
Matteo Lucarelli

Reputation: 1

You can use a pointer:

DatabaseHandler *DGeneDB;
try {
    DGeneDB = new DatabaseHandler("string/to/path");
}catch(DatabaseHandlerExceptions &msg) {
    // your error stuff here
}
DGeneDB->foo();

But don't forget to delete it after use.

Upvotes: 0

Paul Manta
Paul Manta

Reputation: 31597

Does your Databasehandler have an open method, or something similar? If not, create one and modify that constructor so that it doesn't open the database connection anymore (so it won't throw). Your code would look like this:

DatabaseHandler DGenDB;
try {
    DGenDB.open(dbpaths.Dgene_db);
}
catch (DatabaseHandlerExceptions &msg) {
    return 1;
}

Note: In your original code you have a line like this:

DatabaseHandler DGeneDB = DatabaseHandler(dbpaths.Dgene_db);

That is an unusual way to initialize variables in C++. You could have just written:

DatabaseHandler DGeneDB(dbpaths.Dgene_db);

Upvotes: 4

Related Questions