问题描述
首先,我对C ++还是陌生的,我正在尝试学习它。也是stackoverflow的新功能。 很难做到诚实。 如果您在我的代码以及如何改进它方面还有其他意见,请告诉我,因为我仍在学习过程中。
好吧,我只是使用面向对象的程序创建了一个在线预订系统。
好的,所以主要的问题是我不理解为什么 system.setdisplay(1234); 没有打印任何内容。我已经尝试了一切,只是没有加起来。 OnlineBookingSystem是用于调用setdisplay(id)的类,该类随后调用显示类。 如果您能提供帮助,那对我来说意味着世界,而我得到的错误是:
运行时错误:类型为“用户”(solution.cpp)的空指针上的成员调用 摘要:UndefinedBehaviorSanitizer:未定义行为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,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
所做的任何更改都是对副本的更改,而不是对Library
中的system
对象的更改。
要解决此问题,请将返回类型更改为引用:
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;
}
}
,
问题
这取决于您调用system.getUserManager()
返回OnlineBookingSystem
的{{1}}字段的副本,而不是返回 pointer
因此,当您调用manager
时,它会将Michael添加到manager.addToQueue("Michael")
本地的UserManager
实例中,而不是保存在int main()
中的实例中
您的函数system
调用OnlineBookingSystem::setDisplay(size_t)
。由于您已将Michael添加到manager.getNextCustomer()
的其他实例中,因此返回manager
。
如何修复
您只需要修改nullptr
即可返回指向OnlineBookingSystem::getUserManager()
的指针,而不是其副本:
manager
然后修改调用代码以使用指针取消引用运算符(UserManager* getUserManager()
{
return &manager;
}
)而不是句点来访问->
上的方法。