C++:可以从 Class 及其受保护的成员类型继承吗?
C++: Is It OK to Inherit from a Class and Its Protected Member Type?
以下代码是否符合 C++ 标准?
struct B
{
protected:
struct Type {};
};
struct D : B, B::Type
{};
int main()
{
D d;
return 0;
}
我在 Compiler Explorer 上试过了。
MSVC(VS 2017 RTW) 接受它。
gcc(7.3) 和 clang(6.0.0) 拒绝它。
如果 D 派生自 B,它可以访问其受保护的成员,所以这应该是正确的。问题是它在那个编译点是否已经已经 访问,或者它是否只有在类型完成后才能访问。
请注意,如果将两者反过来(将 B 放在逗号后面),它应该会失败。
该代码符合标准,自 C++11 开始,但不在 C++03 中。
C++11 到 C++17 在 [class.access] 部分的介绍中这样说,成员访问控制:
All access controls in clause [class.access] affect the ability to access a class member name from the declaration of a particular entity, including parts of the declaration preceding the name of the entity being declared and, if the entity is a class, the definitions of members of the class appearing outside the class's member-specification.
在那些相同的标准版本中,下面的示例与您的问题非常相似,但甚至有点棘手:
[Example:
class A {
...
protected:
struct B { };
};
...
struct D: A::B, A { };
... The use of A::B
as a base-specifier is well-formed because D
is derived from A
, so checking of base-specifiers must be deferred until the entire base-specifier-list has been seen. -end example]
但我看到了与您相同的结果:g++ 和 clang++ 都拒绝这些程序,无论我给出什么 -std=
参数。这是一对编译器错误。
C++03 有这个而不是我上面引用的第一段:
All access controls in clause [class.access] affect the ability to access a class member name from a particular scope. The access control for names used in the definition of a class member that appears outside of the member's class definition is done as if the entire member definition appeared in the scope of the member's class....
class 定义的 base-specifier 不在那个 class 的范围内,所以 C++03 不允许使用受保护或私有名称作为派生 class 的基 class 的名称,否则可以访问该名称。
以下代码是否符合 C++ 标准?
struct B
{
protected:
struct Type {};
};
struct D : B, B::Type
{};
int main()
{
D d;
return 0;
}
我在 Compiler Explorer 上试过了。 MSVC(VS 2017 RTW) 接受它。 gcc(7.3) 和 clang(6.0.0) 拒绝它。
如果 D 派生自 B,它可以访问其受保护的成员,所以这应该是正确的。问题是它在那个编译点是否已经已经 访问,或者它是否只有在类型完成后才能访问。
请注意,如果将两者反过来(将 B 放在逗号后面),它应该会失败。
该代码符合标准,自 C++11 开始,但不在 C++03 中。
C++11 到 C++17 在 [class.access] 部分的介绍中这样说,成员访问控制:
All access controls in clause [class.access] affect the ability to access a class member name from the declaration of a particular entity, including parts of the declaration preceding the name of the entity being declared and, if the entity is a class, the definitions of members of the class appearing outside the class's member-specification.
在那些相同的标准版本中,下面的示例与您的问题非常相似,但甚至有点棘手:
[Example:
class A { ... protected: struct B { }; }; ... struct D: A::B, A { };
... The use of
A::B
as a base-specifier is well-formed becauseD
is derived fromA
, so checking of base-specifiers must be deferred until the entire base-specifier-list has been seen. -end example]
但我看到了与您相同的结果:g++ 和 clang++ 都拒绝这些程序,无论我给出什么 -std=
参数。这是一对编译器错误。
C++03 有这个而不是我上面引用的第一段:
All access controls in clause [class.access] affect the ability to access a class member name from a particular scope. The access control for names used in the definition of a class member that appears outside of the member's class definition is done as if the entire member definition appeared in the scope of the member's class....
class 定义的 base-specifier 不在那个 class 的范围内,所以 C++03 不允许使用受保护或私有名称作为派生 class 的基 class 的名称,否则可以访问该名称。