List/Vector 迭代器不会更改派生 class 中的 const 引用属性

List/Vector iterator wont change const reference attribute in a derived class

C++ 新手。我不知道(无法找到正确的搜索词)为什么会发生以下情况。

基本上 Parent class 有一个成员 inputsChild class 有一个对 Parent::inputs 的 const 引用和一个 Child::set_inputs() 方法来改变 Parent::inputs。当我有一个 std::list<Child>std::vector<Child> 时,我遍历并尝试 set_inputsParent::inputs 改变,但 Child::input 不变。幕后发生了什么,我将如何解决这个问题?因为我需要使用 lists/vectors.

class Parent {

public:
    Parent() = default;
protected:
    double inputs;
};

class Child : public Parent {

public:

    Child() = default;

    void set_inputs(const double& X) {
        inputs = X;
    }

public:
    const double& input = inputs;
};

int main() {
    using std::cout;
    using std::endl;

    // Without Lists, works outputs '3.0'
    double X1 = 3.0;
    Child test0;
    test0.set_inputs(X1);
    cout << test0.input << endl;


    // Neither Lists or Vectors work, does not output '3.0'
    Child test1, test2, test3;
    std::list<Child> test_lists = { test1, test2, test3 };
    for (std::list<Child>::iterator t = test_lists.begin(); t != test_lists.end(); ++t) {
        t->set_inputs(X1);
        cout << t->input << endl;
    }
}

默认的复制构造函数正在建立从一个实例到另一个实例的引用input。当您将子对象放入容器时,您正在制作子对象的副本。换句话说,您的容器副本的 input 成员仍然引用您的 test1test 等实例的 inputs 成员。因此,当调用 set_inputs 更改实例 Parent::inputs 成员(正在发生)时,它与 input 中包含的 input 引用的 inputs 无关 Child 对象。注意:如果 test1 等在你的容器之前超出范围,这也是悬空引用的方法。

换句话说,默认的复制构造函数是这样做的:

Child(const Child& c) : Parent(c), input(c.input) {}

哎呀。现在 input 成员正在引用 c.input 引用的任何内容;不是 Parent::inputs .

要查看不复制更改声明会发生什么,您可以这样做:std::list<Child> test_lists(3);。现在,当您 运行 您的程序时,它将 运行 “正确”。没有正在制作的副本,因此 input 参考成员没有错误接线。

要解决此问题,您需要确保 input 成员始终固定到其父级 inputs,包括复制操作者。简而言之,添加:

Child(const Child& c) : Parent(c), input(inputs) {}

Childclass.