C++中using暴露私有基类名时GCC与Clang谁的行为符合标准
结论
Clang 的行为符合 C++ 标准,GCC 此处属于非标准兼容的实现。
原理说明
- 首先要明确「注入类名(injected-class-name)」的规则:每个类在自身作用域内会自动注入和类名相同的名称,作为该类的公开成员,也就是说
struct A的作用域内,A这个名字本身就是A的一个公开成员。 - B是
class类型,默认以私有方式继承A,因此A的所有成员(包括注入类名A)在B中的访问权限都会被降为私有,只有B的成员函数和友元有权限访问。 using B::A这行代码首先会触发对B::A的名字查找,找到的就是B路径下继承来的私有注入类名A。D作为B的派生类,没有权限访问B的私有成员,因此这个using声明本身就是非法的。
至于GCC为什么可以编译通过,是因为GCC的实现逻辑额外判断了D还有从C公有继承来的A注入类名可用,忽略了using显式指定的B::路径的访问权限校验,这属于不符合标准的宽松实现。如果你把代码改成using C::A,两个编译器都会正常编译,符合标准预期。
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

