为每个对象增加一个计数器

incrementing a counter for every object

我有一个 class 叫做 Student,在那 class 我有一个 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() returns 每个 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_studentnew_student_1

有人可以帮我吗?

您的代码的问题是每个 Student 对象都有自己的 std::map 副本。您需要他们共享一个 std::map 对象。

共享books字段的最简单方法是使它成为Studentstatic成员,那么你根本不需要复制它,例如:

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() 本身的局部变量,然后你可以将 pointer/reference 传递给每个 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::vectorstd::shared_ptr<Book> 对象,以共享单个图书对象而不仅仅是字符串,而不是管理您自己的完全没有计数器(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("...");
    ...
}