【问题标题】:How to use 'mutable' correctly so the set iterator won't be const?如何正确使用“可变”,以便集合迭代器不会是 const?
【发布时间】:2022-01-06 10:09:16
【问题描述】:

我试图在我的代码中删除员工并将他的薪水改回 0,但我在函数中得到的只是他的 ID。我为集合使用了内置的迭代器,但发现它是 const。我如何使用 mutable 或其他方式将他的薪水更改为 0? 我有一名员工和一名经理——经理可以雇用或解雇该员工,这将改变他的薪水(显然)。 这是我的代码:

class Manager : public Citizen {
    protected:
        int salary;
        std::set<Employee> employees;

void removeEmployee(const int id) {
            mutable std::set<Employee>::iterator employee;

            for (employee = this->employees.begin(); employee != this->employees.end(); employee++) {
                if (employee->getId() == id) {
                    employee->setSalary(0);
                    this->employees.erase(employee);
                    return;
                }
            }
            throw EmployeeNotHired();
        }

我遇到的错误-

C:\Users\User\CLionProjects\hw2Cpp\Manager.h:53:50: error: non-member 'employee' cannot be declared 'mutable'
             mutable std::set<Employee>::iterator employee;
                                                  ^~~~~~~~
C:\Users\User\CLionProjects\hw2Cpp\Manager.h:57:42: error: passing 'const mtm::Employee' as 'this' argument discards qualifiers [-fpermissive]
                     employee->setSalary(0);

我该怎么办?

**** 编辑**** 我尝试将其更改为:

class Employee : public Citizen {
protected:
    mutable int salary;
    mutable int score;
    std::set<Skill> skills;

但我仍然无法将工资更改为 0。

error: passing 'const mtm::Employee' as 'this' argument discards qualifiers [-fpermissive]
                     employee->setSalary(0);

【问题讨论】:

  • mutable 仅适用于成员变量,不适用于局部变量。
  • @Sean 那么在这种情况下我该怎么办?

标签: c++ class error-handling constants


【解决方案1】:

这不是它的工作原理。如果 member 标记为可变 (mutable int salary;) 而不是迭代器,则可以通过 const 引用更改值。

但是,为什么要在删除之前将薪水设置为零?而且无论如何,如果更改集合中的值会影响该集合的顺序,则不允许更改该值,因此通常是个坏主意。

【讨论】:

  • 我尝试更改它,但仍然没有运气。而且我需要改变它,以便他可以被其他地方雇用
  • 该集合存储员工记录的副本,并且该副本在擦除调用时消失。无论如何,要在 const 对象上调用 setSalary,该函数也必须标记为 const。然而,拥有一个改变成员值的const 函数是非常奇怪的。而且代码味道很大。
【解决方案2】:

std::set 的设计确保集合中的元素“无法修改”,即只能通过 const 引用访问它们。这是有充分理由的:std::set 依赖于其元素在整个生命周期中保持不变的顺序来维护其内部搜索树数据结构。

处理方法是:

  1. setSalary 声明为 const 成员函数。 (这不是一个好主意,因为设置薪水可能会以 const 函数不期望的方式修改对象。)
  2. Extract 员工 (C++17)
    //employee->setSalary(0);
    //this->employees.erase(employee);
    auto node = employees.extract(employee);
    node.value().setSalary(0);
    
  3. 选择不同的数据结构,例如从 id 到 Employeestd::vector&lt;Employee&gt;std::unordered_map&lt;int, Employee&gt; 映射。

但是,除非setSalary 函数除了修改Employee 对象之外还有其他效果,否则只需从集合中移除该对象即可;无论如何,该对象在该过程中被删除...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-17
    • 1970-01-01
    • 2014-01-31
    • 2015-08-23
    • 1970-01-01
    • 2018-01-29
    相关资源
    最近更新 更多