C++,运行时错误 : member call on null pointer of type

标签 c++ smart-pointers object-oriented-analysis

首先,我是 c++ 的新手,我正在努力学习它。也是 stackoverflow 的新手。 发现很难说实话。 如果您对我的代码以及我如何改进它有其他意见,请告诉我,因为我仍在学习过程中。

好吧,我只是使用面向对象编程创建了一个在线预订系统。

好吧,主要问题是我不明白为什么 system.setDisplay(1234); 没有打印任何东西。我已经尝试了一切,只是没有加起来。 OnlineBookingSystem 是用于调用 setDisplay(id) 然后调用显示类的类。 如果你能提供帮助,这对我来说意义重大,我得到的错误是:

运行时错误:成员调用“用户”类型的空指针 (solution.cpp) 摘要:UndefinedBehaviorSanitizer:undefined-behavior prog_joined.cpp:179:54

#include <vector>
#include <string>
#include <iostream>
#include <memory>
#include <queue>
using namespace std;

enum class BookGenre
{
    Horror,Adventure,Romance,Comic
};
class Book
{
    private:
        BookGenre genre;
        string title;
        size_t id;
    public:
        Book(string title,size_t id,BookGenre genre):title(title),id(id),genre(genre){}
        string getTitle(){return title;}
        size_t getId(){return id;}
        BookGenre getGenre(){return genre; }
};
class Library
{
    private:
        vector<shared_ptr<Book>> listOfBooks;
    public:
        Library(){};
        void addBook(string title,size_t id,BookGenre genre)
        {
            listOfBooks.push_back(make_shared<Book>(title,id,genre));
        }
        shared_ptr<Book> getBook(size_t id)
        {
            for(auto&x:listOfBooks)
            {
                if(x->getId()==id)
                {
                    return x;
                }
            }
            return nullptr;
        }
        void removeBook(size_t id)
        {
            for(auto it=listOfBooks.begin();it!=listOfBooks.end();it++)
            {
                if((*it)->getId()==id)
                {
                    listOfBooks.erase(it);
                }
            }
        }
};
class User
{
    protected:
        size_t id;
        string username;
     
    public:
        User(size_t id,string username):id(id),username(username)
        {
 
        }
        virtual ~User(){}
        size_t getId(){return id;}
        string getUsername(){return username;}

};
class Employee:public User{
    private:
        double salary;
    public:
        Employee(size_t id,string username,double salary):User(id,username),salary(salary)
        {
        }
        void setSalary(double salary)
        {
            this->salary=salary;
        }
        double getSalary(){return salary;}
     
};
class Customer:public User{
    private:
           bool membership;
    public:
        Customer(size_t id,string username):User(id,username)
        {
            membership=false;
        }
        void setMemberActive()
        {
            membership=true;
        }
        bool isMemberActive()
        {
            return membership;
        }
};
class UserManager
{
    private:
        vector<shared_ptr<User>>listOfUsers;
        queue<shared_ptr<Customer>>queue;
    public:
        UserManager()
        {

        }
      
        void addCustomer(size_t id,string username)
        {
            listOfUsers.push_back(make_shared<Customer>(id,username));
        }
        void removeCustomer(string username)
        {
            for(auto it=listOfUsers.begin();it!=listOfUsers.end();it++)
            {
                if(dynamic_pointer_cast<Customer>(*it))
                {
                    if((*it)->getUsername()==username)
                    {
                        listOfUsers.erase(it);
                    }
                }
            }
        }
        shared_ptr<Customer> getCustomer(string username)
        {
            for(auto it=listOfUsers.begin();it!=listOfUsers.end();it++)
            {
                if(dynamic_pointer_cast<Customer>(*it))
                {
                    if((*it)->getUsername()==username)
                    {
                        return dynamic_pointer_cast<Customer>(*it);
                    }
                }
            }
            return nullptr;
        }
        void addToQueue(string username)
        {
            queue.push(getCustomer(username));
        }
        void removeCurrentCustomer()
        {
            queue.pop();
        }
        shared_ptr<Customer> getNextCustomer()
        {
            if(queue.empty())
            {
                return nullptr;
            }
            return queue.front();
        }
        /*
            same process for user;
        */
};
class Display
{   
    private:
        shared_ptr<Customer> m_customer;
        shared_ptr<Book> m_book;
    public:
        Display(shared_ptr<Customer> _customer,shared_ptr<Book> _book ):m_customer(_customer),m_book(_book)
        {

        }
        shared_ptr<Customer> getUser(){return m_customer;}
        shared_ptr<Book> getBook(){return m_book;}
        void displayInfo()
        {
            cout<<"Customer username: "<<m_customer->getUsername()<<endl;
            cout<<"Member Active: "<<m_customer->isMemberActive();
            cout<<"book id: "<<m_book->getId()<<endl;
            cout<<"book title: "<< m_book->getTitle()<<endl;
        }

};
class OnlineBookingSystem
{
    private:
        UserManager manager;
        Library library;
        shared_ptr<Display>display;
    public:
        OnlineBookingSystem()
        {
            UserManager manager;
            Library library;
            this->manager=manager;
            this->library=library;
            this->display=nullptr;
        }
        Library getLibrary()
        {
            return library;
        }
        UserManager getUserManager()
        {
            return manager;
        }
        void  setDisplay(size_t id)
        {
            display=make_shared<Display>( manager.getNextCustomer(),library.getBook(id));
            display->displayInfo();
        }
        shared_ptr<Display> getDisplay()
        {
            return this->display;
        }
};
int main()
{

    OnlineBookingSystem system;
    auto lib=system.getLibrary();
    lib.addBook("Adventure of Pablo",1234,BookGenre::Adventure);
    auto manager=system.getUserManager();
    manager.addCustomer(2020,"Michael");
    auto _customer=  manager.getCustomer("Michael");
    _customer->setMemberActive();
    manager.addToQueue("Michael");
    system.setDisplay(1234);

    return 0;
}

最佳答案

我看到的问题:

问题1

由于 OnlineBookingSystem::getLibrary() 的返回类型是 Library,因此行

auto lib=system.getLibrary();

lib 构造为 system 中对象的拷贝。对 lib 所做的任何更改都是对拷贝的更改,而不是对 system 中的 Library 对象的更改。

要解决此问题,请将返回类型更改为引用:

Library& getLibrary()
{
    return library;
}

并捕获返回值也作为 main 中的引用。

auto& lib=system.getLibrary();

问题2

与问题 1 类似,但这次是在 OnlineBookingSystem::getUserManager 中。将其返回类型更改为引用:

UserManager& getUserManager()
{
    return manager;
}

并捕获返回值也作为 main 中的引用。

auto& manager=system.getUserManager();

问题3

在每一步都采用防御性编程,直到出现性能瓶颈。如果一个函数的返回值可以是nullptr,则在调用时检查返回值,当返回值确实是nullptr时进行处理。

OnlineBookingSystem::setDisplay 更新为:

    void  setDisplay(size_t id)
    {
        display=make_shared<Display>( manager.getNextCustomer(),library.getBook(id));
        if ( display )
        {
            display->displayInfo();
        }
        else
        {
           // Deal with the nullptr case
           std::cout << "Unable to find a book with id " << id << std::endl;
        }
    }

关于C++,运行时错误 : member call on null pointer of type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64020681/

相关文章:

java - 如何在Java中运行预定的函数?

c++ - 更改 QT 应用程序的 TARGET 编译名称

c++ - 将文件组织到文件夹(模块编程)

c++ - vector 、结构和 std::find

c++ - 使用 boost::shared_ptr 时出错

c++ - boost::scoped_ptr 是否违反逻辑常量准则

java - "instanceof"运算符的这种使用是否被认为是糟糕的设计?

c++ - 如何使用来自另一个分支的类指针访问层次结构一个分支的类的成员?

c++ - weak_ptr 如何知道共享资源已过期?

java - 聚合对象建模的正确方法是什么?