动态分配的对象未初始化

Dynamic allocated object not initializing

本文关键字:初始化 对象 动态分配      更新时间:2023-10-16

我正在尝试为学校的家庭作业准备一个图书馆管理系统。我编写了代码,但在bool Library::add_book(const Book&)函数中,我无法将 book 初始化为动态数组。我重载了= operator来初始化Book类,当我在 main 中声明一个Book对象时,它可以工作。但是对于动态分配的数组,它不起作用。

#include <iostream>
class Author{
public:
std::string name;
Author(){}
Author(const std::string& name){
this -> name = name;
}
};
class Book{
private:
std::string _title, _isbn;
int _edition;
Author *_author = new Author;
public:
Book(){
*_author = Author("NULL");
_isbn = "INVALID";
}
Book(const std::string& title,
const std::string& isbn,
const std::string& author,
int edition){
_title = title;
_isbn = isbn;
_edition = edition;
*_author = Author(author);
}
bool query_isbn(const std::string&);
Book& operator=(const Book&);
friend std::ostream &operator <<(std::ostream &, Book&);
};
class Library{
private:
Book *_book = nullptr;
int *_numberOfBorrows = nullptr;
int _numberOfBook, _maxNumberBook;
public:
Library(int maxNumberBook){
_maxNumberBook = maxNumberBook;
_book = new Book[_maxNumberBook];
_numberOfBorrows = new int[_maxNumberBook];
for(int i = 0; i < _maxNumberBook; i++){
_book[i] = Book();
_numberOfBorrows[i] = 0;
}
}
~Library(){
delete []_book;
_book = NULL;
delete []_numberOfBorrows;
_numberOfBorrows = NULL;
}
bool add_book(const Book&);
void operator+= (const Book&);
const Book& borrow_book(const std::string&);
friend std::ostream& operator <<(std::ostream&, Library&);
};
bool Book::query_isbn(const std::string& isbn){
if(_isbn == isbn)
return true;
else
return false;
}
Book& Book::operator=(const Book& book){
Book ret;
ret._author -> name = book._author -> name;
ret._edition = book._edition;
ret._isbn = book._isbn;
ret._title = book._title;
return ret;
}
std::ostream &operator << (std::ostream& output, Book& obj){
output << obj._author -> name << ", " << obj._title << ", " << obj._isbn << std::endl;
return output;
}
bool Library::add_book(const Book& book){
for(int i = 0; i < _maxNumberBook; i++){
if(_book[i].query_isbn("INVALID")){
_book[i] = book;
_numberOfBook++;
return true;
}
}
return false;
}
void Library::operator+= (const Book& book){
add_book(book);
}
const Book& Library::borrow_book(const std::string& isbn){
for(int i = 0; i < _maxNumberBook; i++){
if(_book[i].query_isbn(isbn)){
_numberOfBorrows[i] = _numberOfBorrows[i] + 1;
return _book[i];
}
}
std::cout << "ISBN with " << isbn << " does not exist" << std::endl;
}
std::ostream& operator <<(std::ostream& output, Library& lib){
for(int i = 0; i < lib._maxNumberBook; i++){
output << lib._book[i];
output << "Borrowed: " << lib._numberOfBorrows[i] << std::endl;
for(int i = 0; i < 38; i++)
output << '=';
std::cout << std::endl;
}
return output;
}
int main(int argc, char** argv){
Library lib(3);
Book obj1("The 8051 Microcontroller & Embedded Systems", "1234-456789123", "Mazidi", 1),
obj2("Fundamentals of Database Systems", "7899-456456123", "Elmasri", 2),
obj3("Electric Circuits", "1478-258963258", "Nilsson", 3);
lib.add_book(obj1);
lib.add_book(obj2);
lib.add_book(obj3);
lib.borrow_book("6584-258963258");
lib.borrow_book("1234-456789123");
lib.borrow_book("7899-456456123");
lib.borrow_book("1478-258963258");
std::cout << lib;

return 0;
}

我希望它输出书籍属性,但它输出与下面相同...

ISBN with 6584-258963258 does not exist
ISBN with 1234-456789123 does not exist
ISBN with 7899-456456123 does not exist
ISBN with 1478-258963258 does not exist
NULL, , INVALID
Borrowed: 0
======================================
NULL, , INVALID
Borrowed: 0
======================================
NULL, , INVALID
Borrowed: 0
======================================

互相玩有几个错误。我将只介绍与所问问题直接相关的两个问题。

问题1:

bool Library::add_book(const Book& book){
for(int i = 0; i < _maxNumberBook; i++){
if(_book[i].query_isbn("INVALID")){
_book[i] = book;
_numberOfBook++;
return true;
}
}
return false;
}

利用

Book& Book::operator=(const Book& book){
Book ret;
ret._author -> name = book._author -> name;
ret._edition = book._edition;
ret._isbn = book._isbn;
ret._title = book._title;
return ret;
}

这不会分配给给定的Book.它不是分配给*this,而是创建一个新的Book并分配给它。因此,作业不执行任何操作。

旁注:由于Book ret;是局部变量,因此无法安全地返回对它的引用。它在函数末尾超出范围,调用方左侧持有无效引用。编译器可能会警告您这一点。

operator=应该看起来像

Book& Book::operator=(const Book& book){
*_author = *book._author;
_edition = book._edition;
_isbn = book._isbn;
_title = book._title;
return *this;
}

但这根本不是必要的。

使用自定义operator=的原因大概是为了处理_author成员,即指针。这是使用自有指针的糟糕地方。Book不应拥有Author的所有权,以便许多书籍可以共享相同的Author,或者应自动分配_author,以便许多Book可以拥有相同Author的副本。目前使用的是复制方法,但有一个指向动态分配Author的指针。此处不适合使用动态分配进行复制。

使用自动变量或非拥有指针(或std::shared_ptr(进行复制消除了对自定义operator=的需要,消除了这个问题。请参阅零法则了解更多信息。你选择哪条路是你必须做出的决定。

问题2

const Book& Library::borrow_book(const std::string& isbn){
for(int i = 0; i < _maxNumberBook; i++){
if(_book[i].query_isbn(isbn)){
_numberOfBorrows[i] = _numberOfBorrows[i] + 1;
return _book[i];
}
}
std::cout << "ISBN with " << isbn << " does not exist" << std::endl;
}

在所有情况下都不返回Book &。如果找不到这本书,borrow_book的来电者不会得到任何回复,他们会得到一些完全不确定的东西。现代编译器也会标记此错误。

这里有几个常见的解决方案。返回std::optionalstd::pair<bool, const Book*>都提供了可以测试有效结果的内容。返回const Book *允许返回nullptr,再次可以测试有效Book。该函数还可以返回bool并更新参数。

这可能是我在 C 语言中的成长经历,但我认为在这里返回一个原始的、无主的指针是最合适的,但这是意见。

const Book * Library::borrow_book(const std::string& isbn){
for(int i = 0; i < _maxNumberBook; i++){
if(_book[i].query_isbn(isbn)){
_numberOfBorrows[i]++;
return &_book[i];
}
}
std::cout << "ISBN with " << isbn << " does not exist" << std::endl;
return nullptr;
}

旁注:由于_maxNumberBook与图书馆中实际存储的书籍数量没有任何联系,因此for(int i = 0; i < _maxNumberBook; i++){风险很高。_book[i]可能尚未设置为定义的值。