JEC
JEC

Reputation: 21

Problem with C++ class instance not being recognized

This is for "homework" but this is not an algorithm question, but rather a programming issue. As part of a project for my Data Structures class, I have to write a class to act as a database. That part is done. I am not asking about the algorithm, but rather, trying to isolate what is clearly a stupid bug on my part.

PeopleDB has two constructors, the default one and one that takes as a parameter an input file and reads it into the database to initialize it.

Here is the code snippet, the problem is described below it:

#include "People.h" // People class definition
#include "PeopleDB.h" // People database class
#include "PrecondViolatedExcep.h"

using namespace std;

int main(int argc, char *argv[])
{
    // Define variables
    string infilename;
    PeopleDB mydb;

    // Get the filename of the text file to process
    infilename = argv[1];

    // Try to open import the data into a database instance
    try
    {
        cout << "Attempting to import DB entries from "<< infilename << endl;
        PeopleDB mydb(infilename);
        cout << "# A total of "<< mydb.countEntries() << " DB entries loaded." << endl;
    }
    catch(PrecondViolatedExcep e)
    {
        cout << e.what() << endl;
        cout << "Exiting program.";
        exit(1);
    }

    // Display database contents
    cout << endl;
    cout << "# A total of "<< mydb.countEntries() << " DB entries found before display." << endl;

    return 0;
}  // end main

The problem is if I don't include the PeopleDB mydb; constructor at the top of the main() loop, the compiler barfs saying it doesn't recognize the mydb.countEntries() in the second to last line of the main loop. But if I do include it, it is clear that the mydb within the try loop doesn't survive because the output of the program is:

Attempting to import DB entries from testinput.txt
# A total of 7 DB entries loaded.

# A total of 0 DB entries loaded.

I didn't want to use the same variable (mydb) twice (I actually assumed this would error out during compiling), but for some reason creating the mydb instance of PeopleDB inside the try block doesn't seem to survive to be outside the block. I am sure this is something stupid on my part, but I am not seeing it. It has been a long day, so any suggestions would be appreciated.

Upvotes: 1

Views: 390

Answers (3)

smac89
smac89

Reputation: 43098

Try using move-assignment inside the try block:

mydb = std::move(PeopleDB(infilename));

The reason why I suggested this, is because it avoids creating a new object inside the try block because this object will disappear after the scope of the try block ends.

The reason for using move is to prevent creating the object twice:

  • once with the constructor call
  • another with the copy-constructor call

However, now I realize that the std::move is redundant because PeopleDB(infilename) is already an rvalue reference, and compiler will be smart enough to do the move itself.

So my new suggestion is to just do:

mydb = PeopleDB(infilename);

Upvotes: 0

3CxEZiVlQ
3CxEZiVlQ

Reputation: 38499

You declare two independent mydb objects.

Either perform all actions in the try-catch block, or move connecting to another function.

PeopleDB connect(const std::string& infilename) {
    try
    {
        cout << "Attempting to import DB entries from "<< infilename << endl;
        PeopleDB mydb(infilename);
        cout << "# A total of "<< mydb.countEntries() << " DB entries loaded." << endl;
        return mydb;
    }
    catch(PrecondViolatedExcep e)
    {
        cout << e.what() << endl;
        cout << "Exiting program.";
        exit(1);
    }
    return PeopleDB{};
}

int main(int argc, char *argv[])
{
    // Get the filename of the text file to process
    string infilename = argv[1];
    PeopleDB mydb = connect(infilename);

    // Display database contents
    cout << endl;
    cout << "# A total of "<< mydb.countEntries() << " DB entries found before display." << endl;

    return 0;
}  // end main

Upvotes: 3

alagner
alagner

Reputation: 4062

You are creating two objects myDb of type PeopleDB: one at the beginning of main, the other one in the try block. That latter one loads the data, but gets gets destroyed with the end of that try block's scope. The second one being printed is the one created in the main block, and that one has never loaded the data.

There are multiple ways to fix that, e.g. provide a method to load data and call it inside the try block. Another option is to copy/move/swap the "inside" one with the "outside" one before the try block ends (but I'd provide different names in such case). Your call, but bottom line is: at that point you have two different objects: one the data is loaded to, and the other one it is printed from (with empty results).

Upvotes: 3

Related Questions