C++子类调用父类方法时自身成员变量未被修改的原因
问题根因
这个异常是C++作用域名字遮蔽(Name Hiding)+ 类成员访问的作用域匹配规则共同导致的,具体逻辑如下:
- 你在子类
CircularLinkedList中重复声明了和父类LinkedList完全同名的head、lastNode、_size三个成员,这一行为不会覆盖父类的同名成员,反而会让CircularLinkedList的实例内存中同时存在两套完全独立的同名成员:一套是从父类继承得到的,一套是子类自身定义的。 - 当你在子类重写的
deAppend方法中调用父类实现LinkedList::deAppend(data)时,该方法是在父类作用域下定义的,其内部通过this指针访问head、lastNode、_size时,只会匹配父类作用域下的那套成员,完全感知不到子类自定义的同名成员,因此执行完父类方法后,只有父类继承来的三个成员被正确赋值,子类自己定义的三个成员始终停留在构造函数初始化的nullptr、0值状态。 - 父类方法执行完成后,你写的
this->lastNode->next = this->head代码位于子类作用域下,这里访问的lastNode、head会优先匹配子类自身定义的那两个指针——这两个指针还是初始值nullptr,对空指针解引用访问next成员,就会触发空指针访问异常。
调试截图里能清晰看到两套同名成员同时存在、赋值状态不一致的现象:
修复方式
核心是删除子类中重复定义的同名成员,直接复用父类继承来的成员即可,修复后的子类代码如下:
class CircularLinkedList : public LinkedList { public : // 移除重复声明的head、lastNode、_size成员,直接复用父类定义的这三个成员 CircularLinkedList() = default; void deAppend(int data) override; }; void CircularLinkedList::deAppend(int data) { LinkedList::deAppend(data); // 此处访问的是父类继承来的lastNode、head,已被父类方法正确赋值 lastNode->next = head; }
额外注意:当前父类
LinkedList的deAppend是头插实现,仅第一次插入节点时会更新lastNode,后续头插不会修改lastNode(符合尾节点始终是第一个插入节点的逻辑),循环链表每次头插后都将尾节点next指向新头节点的逻辑是成立的。
内容的提问来源于stack exchange,提问作者Sarthak Patel
相关产品推荐
相关产品推荐


