C++中的成员名称查找过程是怎样的?相关子对象术语有何关联?
术语定义先明确
先把两个你困惑的术语用实际代码场景解释清楚:
- base class subobject(基类子对象):当你写一个派生类继承某个基类的时候,派生类对象内存布局里自动包含的那个完整基类实例,就叫基类子对象。比如:
class Base { int x; }; class Derived : public Base { int y; };
你创建一个Derived d;的时候,d的内存里首先存的就是一个完整的Base类型实例,这个实例就是d的基类子对象。如果是多继承,就会对应多个基类子对象,虚继承的情况下还会做共享处理。
- member subobject(成员子对象):类中定义的非静态成员变量对应的实例,就是成员子对象。比如上面
Derived里的int y,还有Base里的int x,都是对应类实例的成员子对象。如果类成员是自定义类类型,那这个成员本身也会包含它自己的基类子对象、成员子对象。
实际场景下成员名称查找的执行逻辑
我们用实际代码举例,查找逻辑可以拆解为三步:
- 首先确定查找的起始子对象集合:比如你写
d.x,查找的起始点就是d对应的Derived类型的完整对象的子对象集合,默认包含自身、所有直接/间接基类的子对象。 - 在当前层级的子对象里找目标名称:先在派生类自身的作用域里找有没有叫
x的成员,如果找到就停止查找,返回结果。 - 递归遍历基类子对象查找:如果当前层级没找到,就去每个直接基类的基类子对象的作用域里查找,如果多个基类子对象里都找到了同名成员,就会报歧义错误。
举个歧义的例子:
class A { public: int x; }; class B { public: int x; }; class C : public A, public B {}; int main() { C c; c.x = 10; // 报错:x的查找歧义,因为A的基类子对象和B的基类子对象里都有x }
两个术语和成员名称查找的关联
标准里反复提这两个子对象,本质是在明确名称查找的「作用域遍历范围」和「冲突判定规则」:
- 名称查找的遍历顺序本质就是从完整对象出发,依次遍历自身成员子对象对应的作用域、所有基类子对象对应的作用域,直到找到对应名称或者遍历完所有范围。
- 只有当名称在不同的子对象里被找到时,才会判定为歧义,如果是同一个子对象里的多次声明(比如重载函数)就不会判定为歧义。
- 虚继承场景下同一个基类的基类子对象只会被共享一份,所以查找的时候不会出现同一个基类成员被找到多次的问题,而非虚多继承下每个继承路径都会产生独立的基类子对象,就可能出现重复查找的冲突。
内容的提问来源于stack exchange,提问作者user15071942
相关产品推荐
相关产品推荐

