C++ 使用带有类和构造函数的虚拟函数打印图书信息

C++ 使用带有类和构造函数的虚拟函数打印图书信息,c++,class,oop,c++11,virtual-functions,C++,Class,Oop,C++11,Virtual Functions,我已经到了这个项目的最后一步了,我一直在做什么。该项目将获取一个包含书籍信息的输入文件,如下所示: A Book on C Al Kelly and Ira Pohl Addison-Wesley, Fifth Edition 1998. 0201183994 C How to Program Paul Deitel and Harvey Deitel Prentice Hall Sixth Edition 2010 0136123562 然后使用多个选项打印它。我将把所有代码放在这里,这样

我已经到了这个项目的最后一步了,我一直在做什么。该项目将获取一个包含书籍信息的输入文件,如下所示:

A Book on C
Al Kelly and Ira Pohl
Addison-Wesley, Fifth Edition 1998.
0201183994

C How to Program
Paul Deitel and Harvey Deitel
Prentice Hall Sixth Edition 2010
0136123562
然后使用多个选项打印它。我将把所有代码放在这里,这样您就可以编译并查看每个选项的功能。具体来说,我在选项5上遇到了麻烦。对于选项5,我需要:

  • 在每本书上输入更多信息。我需要有两个子类,
    InfoBookRecord
    包含price和author传记,以及
    TypeBookRecord
    包含图书类型
  • 使用虚拟函数打印新信息。我认为在类
    ListRecords
    中创建虚拟函数是有意义的,但是分级键似乎暗示我应该将它们用于两个子类
    InfoBookRecord
    TypeBookRecord
    。我想不出任何办法来做那件事
  • 标题h:

    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <cassert>
    #include <fstream>
    #include <algorithm>
    using namespace std;
    
    #define TABLE_SIZE 200
    
    class BookRecord{
      public:
        BookRecord(string input_title, string input_author, string input_publisher, int input_isbn);
        string getTitle();
        string getAuthor();
        string getPublisher();
        int getISBN();
    
      private:
        string title;
        string author;
        string publisher;
        int isbn;
    };
    
    class InfoBookRecord: public BookRecord {
      public:
        InfoBookRecord(string input_title, string input_author, string input_publisher, int input_isbn, double input_price, string input_authorBio) : BookRecord(input_title,input_author,input_publisher,input_isbn) {
          price=input_price;
          authorBio=input_authorBio;}
        double getPrice();
        string getAuthorBio();
    
      private:
        double price;
        string authorBio;
    };
    
    class TypeBookRecord: public BookRecord {
      public:
        TypeBookRecord(string input_title, string input_author, string input_publisher, int input_isbn, string input_genre) : BookRecord(input_title,input_author,input_publisher,input_isbn){
          input_genre.resize(15);
          genre=input_genre;}
        string getGenre();
    
      private:
        string genre;
    };
    
    class ListRecords{
      public:
        ListRecords(char filename[]);
        void insertBookInfo(BookRecord record);
        //virtual void printBookInfo(int bookISBN);
        void printBookInfo(int bookISBN);
        void printListByISBN();
        void printListByTitle();
        BookRecord ** books;
        InfoBookRecord ** books2;
        TypeBookRecord ** books3;
        int line_num;
        int k;
        string garbage;
    };
     // problem here
    /*
    class extraListRecords: public ListRecords{
      public:
        extraListRecords();
        void printBookInfo(int bookISBN){
          cout << "testing 1 2 3 " << endl;
        }
    };*/ 
    
    我把给我带来麻烦的两个部分注释掉了。一个在header.h的末尾,另一个在main.cpp的末尾附近

    当我尝试这样做时,我得到了错误

    main.cpp:(.text+0x4c7): undefined reference to `extraListRecords::extraListRecords()'
    collect2: error: ld returned 1 exit status
    make: *** [myprogam] Error 1
    
    我用虚拟函数尝试了该子类的一些其他尝试,例如将book2和book3的初始化添加到其构造函数体中,从而将其构造函数编写为
    extraListRecords(char filename[]):ListRecords(filename){/ListRecords.cpp中的代码块在第55行左右/}


    非常感谢你的帮助

    您需要为extraListRecords提供构造函数定义

    class extraListRecords: public ListRecords {
      public:
        extraListRecords() = default;
        //                 ^^^^^^^^^^
    
    }; 
    

    我想出来了。这个问题相当愚蠢。我只是忘了刷新整数上的cin和getline之间的缓冲区。


    虚拟函数完全可以作为头中的构造函数使用。

    现在我得到
    main.cpp:90:24:错误:使用删除的函数'extraListRecords::extraListRecords()'extraListRecords extras;^在main.cpp:17:0:header.h:68:5中包含的文件中:注意:“extraListRecords::extraListRecords()”被隐式删除,因为默认定义的格式不正确:extraListRecords()=default;^header.h:68:5:错误:调用“ListRecords::ListRecords()”header时没有匹配的函数。h:68:5:注意:候选函数为:header.h:53:5:注意:ListRecords::ListRecords(char*)ListRecords(char文件名[]);^[…]
    基类没有默认构造函数,因此派生类必须使用文件名调用基类上的相应构造函数。当我这样做时,它编译时不会出错,但当我运行程序时,它始终使用基类函数。
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <cassert>
    #include <fstream>
    #include <algorithm>
    #include "header.h"
    using namespace std;
    
    #define TABLE_SIZE 200
    
    int main(int argc, char* argv[]){
      char filename[50];
      cout << "Enter the name of a file to load:" << endl;
      cin >> filename;
    
      ListRecords listrecords(filename);
    
      while(true){ // looping for the selection menu
        int selection, n;
        cout << "Please select a menu option:\n1) Insert a book record into the list\n2) Print information of a book with a given ISBN number\n3) Print the list of books sorted by ISBN\n4) Print the list of books sorted alphabetically by title\n5) Print the books also with info on price, author biography, and genre.\n6) Quit the program" << endl;
        cin >> selection;
        if(cin.fail()){ // make sure input is a digit
          cout << "Invalid selection. Quitting program..." << endl;
          break;
        }
    
        if(selection==1){
          string in_title;
          string in_author;
          string in_publisher;
          int in_isbn;
          string junk;
          getline(cin, junk);
          cout << endl << "Please enter a title: ";
          getline(cin, in_title);
          cout << "Please enter an author: ";
          getline(cin, in_author);
          cout << "Please enter a publisher: ";
          getline(cin, in_publisher);
          cout << "Please enter an ISBN: ";
          cin >> in_isbn;
    
          BookRecord new_record(in_title, in_author, in_publisher, in_isbn);
    
          listrecords.insertBookInfo(new_record);
          cout << endl << "The record has been added to the list." << endl;
          cout << endl << endl;
        }
    
        if(selection==2){
          int in_isbn;
          cout << endl << "Please enter ISBN number: " << endl;
          cin >> in_isbn;
          listrecords.printBookInfo(in_isbn);
          cout << endl << endl;
        }
    
        if(selection==3){
          cout << endl;
          listrecords.printListByISBN();
          cout << endl << endl;
        }
    
        if(selection==4){
          cout << endl;
          listrecords.printListByTitle();
          cout << endl << endl;
        }
    
        if(selection==5){
          int in_isbn;
          cout << endl << "Please enter ISBN number: " << endl;
          cin >> in_isbn;
    
    cout << endl << "List of books also with info on price and author biography: " << endl;
    
          cout << endl << endl;
    
          // problem here
          // extraListRecords extras;
          //ListRecords *bookextras= &extras;
    
          // bookextras->printBookInfo(in_isbn);
    
    
    cout << endl << "List of books also with info on genre: " << endl;
    
    
        }
    
        if(selection==6){
          cout << endl << "Program terminating normally..." << endl;
          break;
        }
    
      } // end of while(true) loop
    
      return 0;
    };
    
    LFLAGS = -Wno-write-strings -std=c++11
    CFLAGS = -Wno-write-strings -std=c++11 -c
    
    myprogam: main.o BookRecord.o ListRecords.o
            g++ $(LFLAGS) -o myprogram main.o BookRecord.o ListRecords.o header.h
    
    main.o: main.cpp header.h
            g++ $(CFLAGS) main.cpp
    
    BookRecord.o: BookRecord.cpp header.h
            g++ $(CFLAGS) BookRecord.cpp
    
    ListRecords.o: ListRecords.cpp header.h
            g++ $(CFLAGS) ListRecords.cpp
    
    clean:
            rm *.o
            rm myprogram
    
    main.cpp:(.text+0x4c7): undefined reference to `extraListRecords::extraListRecords()'
    collect2: error: ld returned 1 exit status
    make: *** [myprogam] Error 1
    
    class extraListRecords: public ListRecords {
      public:
        extraListRecords() = default;
        //                 ^^^^^^^^^^
    
    };