我有一个名为Student
的类,在这个类中,我有一个std::map
的书籍,它看起来像这样:
std::map<std::string,int>books;
string
为书名,int
为拥有同一本书的学生人数。
然后我创建了一个新的Student
,当我这样做的时候,我想让Student
也得到同样的书,所以我做了一个这样的复制:
new_student->getBookmap() = old_student->getBookmap();
new_student_3->getBookmap() = old_student->getBookmap();
getBookmap()
返回每个Student
对应的map
。我把他们作为private
成员。
新的Student
获得相同的map
的精确副本,现在我想增加计数器,但计数器也应该为所有三个Student
增加。
但是,如果我增加一个Student
的计数器,其他Student
的计数器不会增加。
for (auto it = new_student->getBookmap().begin(); it != new_student->getBookmap().end(); it++)
{
it->second++;
}
当我这样做时,计数器只增加new_student
,而不增加old_student
和new_student_1
。
代码的问题是每个Student
对象都有自己的std::map
副本。您需要它们共享一个std::map
对象。
共享books
字段最简单的方法是使其成为Student
的static
成员,然后你根本不需要复制它,例如:
using bookCounter = std::map<std::string, int>;
class Student {
private:
static bookCounter books;
...
void checkoutBook(std::string bookName);
void returnBook(std::string bookName);
...
};
bookCounter Student::books;
void Student::checkoutBook(std::string bookName)
{
books[bookName]++;
}
void Student::returnBook(std::string bookName)
{
books[bookName]--;
}
int main()
{
...
new_student = new Student();
new_student->checkoutBook("...");
...
new_student->returnBook("...");
...
}
或者,您可以将books
声明为全局变量,例如在main()
附近,然后在需要时仅在Students
内部引用该变量,例如:
class Student {
...
};
using bookCounter = std::map<std::string, int>;
extern bookCounter books;
void Student::checkoutBook(std::string bookName)
{
books[bookName]++;
}
void Student::returnBook(std::string bookName)
{
books[bookName]--;
}
bookCounter books;
int main()
{
...
}
或者,您可以使books
成为main()
本身的局部变量,然后您可以将指针/引用传递给每个Student
,例如:
using bookCounter = std::map<std::string, int>;
class Student {
private:
bookCounter &books;
...
public:
Student(bookCounter &books) : books(books) {}
...
void checkoutBook(std::string bookName);
void returnBook(std::string bookName);
...
};
void Student::checkoutBook(std::string bookName)
{
books[bookName]++;
}
void Student::returnBook(std::string bookName)
{
books[bookName]--;
}
int main()
{
bookCounter books;
...
new_student = new Student(books);
new_student->checkoutBook("...");
...
new_student->returnBook("...");
...
}
或者,您可以考虑使用std::shared_ptr
在各种Student
对象之间共享单个std::map
对象,例如:
using bookCounter = std::map<std::string, int>;
class Student {
private:
std::shared_ptr<bookCounter> books;
...
public:
Student(std::shared_ptr<bookCounter> books) : books(books) {}
...
void checkoutBook(std::string bookName);
void returnBook(std::string bookName);
...
};
void Student::checkoutBook(std::string bookName)
{
(*books)[bookName]++;
}
void Student::returnBook(std::string bookName)
{
(*books)[bookName]--;
}
int main()
{
auto books = std::make_shared<bookCounter>();
...
new_student = new Student(books);
new_student->checkoutBook("...");
...
new_student->returnBook("...");
...
}
在这种情况下,您可以考虑将std::map
更改为std::shared_ptr<Book>
对象的std::vector
,以共享单个图书对象而不仅仅是字符串,并且根本不管理您自己的计数器(std::shared_ptr
有自己的计数器,您可以通过其use_count()
方法查询),例如:
struct Book : std::enable_shared_from_this<Book>
{
std::string name;
...
int checkoutCount() const;
[[nodiscard]] static std::shared_ptr<Book> create();
private:
Book() = default;
};
using bookPtr = std::shared_ptr<Book>;
class Student {
private:
std::vector<bookPtr> books;
...
public:
...
void checkoutBook(std::string bookName);
void returnBook(std::string bookName);
...
};
std::vector<bookPtr> library;
std::shared_ptr<Book> Book::create()
{
return std::shared_ptr<Book>(new Book);
}
int Book::checkoutCount() const
{
auto pthis = shared_from_this();
return (pthis.use_count() - 2); // not counting pthis and the library ...
}
void Student::checkoutBook(std::string bookName)
{
auto iter = std::find_if(library.begin(), library.end(),
[&](bookPtr &book){ return book->name == bookName; }
);
if (iter != library.end())
books.push_back(*iter);
}
void Student::returnBook(std::string bookName)
{
auto iter = std::find_if(books.begin(), books.end(),
[&](bookPtr &book){ return book->name == bookName; }
);
if (iter != books.end())
books.erase(*iter);
}
int main()
{
// populate library with Books as needed...
...
new_student = new Student();
new_student->checkoutBook("...");
...
new_student->returnBook("...");
...
}