子类同名变量访问不到父类值是因为作用域屏蔽而非覆盖;java中由声明类型决定访问哪个变量,c++中需用parent::name显式访问父类变量。

子类同名变量为什么访问不到父类的值?
因为“隐藏”不是覆盖,也不是重载,而是作用域屏蔽——子类定义了同名变量后,编译器在子类作用域里查到第一个匹配的 name 就停了,根本不会继续往上翻父类。这和函数调用时的动态绑定无关,纯属静态查找规则。
- Java 中:
obj.name的结果完全由obj的**声明类型**决定,不是运行时对象类型 - C++ 中:默认访问子类成员;要访问父类同名变量,必须显式写
Parent::name - 隐藏不看类型、不看修饰符,只要名字一样就触发(
public int x和private String x也能互相隐藏)
Java 里怎么安全访问被隐藏的父类变量?
不能靠转型“绕过去”,也不能靠多态自动切换——变量访问是编译期绑定的。唯一可靠方式是明确告诉编译器你要哪个作用域的变量。
- 实例变量:用
super.name(仅限非private) - 静态变量:用
Parent.name(哪怕子类有同名static变量) - 别试图用
((Parent)obj).name——如果obj声明类型就是Parent,那没问题;但若声明为Child,强制转成Parent后再点.name,依然访问的是Parent类型下可见的那个变量(也就是父类自己的,不是子类隐藏的那个)
C++ 中父子同名变量共存时内存和访问怎么算?
它们是两个独立变量,各自占内存空间,地址不同。子类对象内存布局里,父类部分和子类新增部分是分开排布的,num 在父类子对象里一份,在子类区域又一份。
- 直接写
c.num→ 访问子类定义的num - 写
c.Parent::num→ 跳进父类子对象区域读取 - 没有
virtual或指针偏移参与,纯粹是编译器根据作用域解析出来的地址偏移 - 调试时在监视窗口里展开
c,能看到两个num字段并列存在,印证它们物理隔离
为什么方法可以重写而变量只能隐藏?
这是语言设计的根本分野:方法调用支持运行时绑定(多态),变量访问只走编译时作用域链。你不能指望 obj.field 在运行时根据实际类型切换字段,它连字段地址都是编译期确定的。
- Java 没有“变量多态”,只有“方法多态”;C++ 同理,
virtual不适用于变量 - 误以为“子类变量覆盖父类”是常见错觉——其实父类字段还在,只是被遮住了
- 真正危险的操作:在父类方法里读
this->x,结果却因子类隐藏了x而行为异常(尤其当父类逻辑依赖该字段时)







