无法识别 C++ 类实例的问题

时间:2021-07-31 19:53:56

标签: c++ c++11

这是给“家庭作业”的,但这不是算法问题,而是编程问题。作为我的数据结构类项目的一部分,我必须编写一个类来充当数据库。那部分就完成了。我不是在询问算法,而是试图找出我认为明显愚蠢的错误。

PeopleDB 有两个构造函数,一个是默认构造函数,另一个是将输入文件作为参数并将其读入数据库以对其进行初始化。

这是代码片段,问题描述如下:

#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

问题是,如果我不在 main() 循环的顶部包含 PeopleDB mydb; 构造函数,编译器就会说它无法识别 mydb.countEntries () 在主循环的倒数第二行。但是如果我确实包含它,很明显 try 循环中的 mydb 不会存活,因为程序的输出是:

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

# A total of 0 DB entries loaded.

我不想使用相同的变量 (mydb) 两次(我实际上认为这会在编译期间出错),但出于某种原因创建了 mydb在 try 块内的 PeopleDB 实例似乎无法在块外存活。我确信这对我来说是愚蠢的,但我没有看到它。这是漫长的一天,所以任何建议将不胜感激。

3 个答案:

答案 0 :(得分:3)

您正在创建两个 myDb 类型的对象 PeopleDB:一个在 main 的开头,另一个在 try 块中。后一个加载数据,但在 try 块的范围结束时被破坏。 正在打印的第二个是在主块中创建的那个,并且那个从未加载过数据。

有多种方法可以解决这个问题,例如提供一种方法来加载数据并在 try 块内调用它。另一种选择是在 try 块结束之前复制/移动/交换“内部”块与“外部”块(但在这种情况下我会提供不同的名称)。您的调用,但最重要的是:此时您有两个不同的对象:一个是加载数据,另一个是从中打印数据(结果为空)。

答案 1 :(得分:3)

您声明了两个独立的 mydb 对象。

要么执行 try-catch 块中的所有操作,要么移动连接到另一个函数。

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

答案 2 :(得分:0)

尝试在 try 块内使用移动赋值:

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

我之所以这么建议,是因为它避免在 try 块内创建新对象,因为在 try 块的作用域结束后,该对象将消失。

使用 move 的原因是为了防止创建对象两次:

  • 使用构造函数调用一次
  • 另一个使用复制构造函数调用

但是,现在我意识到 std::move 是多余的,因为 PeopleDB(infilename) 已经是一个右值引用,并且编译器将足够聪明以自行完成移动。

所以我的新建议是:

mydb = PeopleDB(infilename);