我无法理解为什么从子类中删除变量后输出会发生变化

I am having trouble understanding why does the output change after removing a variable from a subclass

本文关键字:输出 变量 变化 删除 为什么 子类      更新时间:2023-10-16

您好,下面的代码中的输出是"A",我不明白为什么从子类 B 中删除值变量后输出("值"变量(更改为"B">

#include <iostream>
#include <string>
using namespace std;
class A {
public:
    string value;
    A(){
        value = "A";
    }
    void display(){
        cout<<value<<endl;
    }
};
class B : public A{
public:
    string value;
    B(){
        value = "B";
    }

};
int main(){
    A *c = new B();
    c->display();
}

当两个类都有一个名为 value 的变量时,B构造函数引用B::value

B中删除它后,它开始引用A::value,并分配给它。

将变量设为私有A::value,您将看到编译器抱怨您尝试访问无法访问的成员变量。

C++ 中没有覆盖变量这样的事情,您无需在 B 中重新声明value即可使其可访问(Apublicprotected为您做到这一点(。事实上,当您在 B 中声明string value时,它会创建一个不同的成员,隐藏另一个非限定标识符。B::B()中的作业分配给此,A::value保持不变。(不过,如果您愿意,您仍然可以从B内部专门引用A::value

如果从B中删除value,则会看到继承的A::value B::value,它们引用同一对象。为此分配"B"会更改A::display()看到的内容。

您可能有意

如果要明确表示要从A中获取名称value,可以使用using

class B : public A{
public:
    using A::value;
    B(){
        value = "B";
    }
};

此构造的主要用途是

  • 暴露成员,例如,如果A仅派生自 AS class B : private A

  • 引用依赖作用域中的成员,例如,如果您正在编写template<class A> class B : public A。(不知道编译器的先验A不会知道你在构造函数中指的是什么value,所以它需要一个提示,它应该是模板参数的成员。

为什么它很好

在派生类中允许同名的成员可能很有用。假设您正在编写类B,并依赖于其中名为 value 的成员,该成员具有一些语义。您不在乎是否有人独立决定向您A基类添加一些实用程序,他们也需要一个value。你不希望错误,因为另一个是const或其他东西。但最重要的是,您不希望它突然开始覆盖您在B逻辑中放入该成员变量的任何内容。

另一个有趣的情况是,当设计具有非固定继承图的std::tuple之类的东西时。但这是一个单独的讨论。