我试图完全理解C++标准[class.access]部分的多个段落中定义的成员访问规则。它们相当complex or even confusing,因此我需要一个简短但准确而详尽的摘要。
我编译了该程序,以测试几种情况下 protected 成员的可访问性(因为 protected 成员的规则最复杂):1
#include <iostream>
class B {
protected:
int i = 1;
static int const I = 1;
};
class X: public B {
protected:
int j = 2;
static int const J = 2;
public:
void f();
friend void g();
};
class D: public X {
protected:
int k = 3;
static int const K = 3;
};
void X::f() {
B b;
X x;
D d;
//std::cout << b.i; // error: 'i' is a protected member of 'B'
std::cout << b.I;
std::cout << x.i;
std::cout << x.I;
std::cout << x.j;
std::cout << x.J;
std::cout << d.i;
std::cout << d.I;
std::cout << d.j;
std::cout << d.J;
//std::cout << d.k; // error: 'k' is a protected member of 'D'
//std::cout << d.K; // error: 'K' is a protected member of 'D'
}
void g() {
B b;
X x;
D d;
//std::cout << b.i; // error: 'i' is a protected member of 'B'
//std::cout << b.I; // error: 'I' is a protected member of 'B'
std::cout << x.i;
std::cout << x.I;
std::cout << x.j;
std::cout << x.J;
std::cout << d.i;
std::cout << d.I;
std::cout << d.j;
std::cout << d.J;
//std::cout << d.k; // error: 'k' is a protected member of 'D'
//std::cout << d.K; // error: 'K' is a protected member of 'D'
}
int main() {
B b;
X x;
D d;
//std::cout << b.i; // error: 'i' is a protected member of 'B'
//std::cout << b.I; // error: 'I' is a protected member of 'B'
//std::cout << x.i; // error: 'i' is a protected member of 'B'
//std::cout << x.I; // error: 'I' is a protected member of 'B'
//std::cout << x.j; // error: 'j' is a protected member of 'X'
//std::cout << x.J; // error: 'J' is a protected member of 'X'
//std::cout << d.i; // error: 'i' is a protected member of 'B'
//std::cout << d.I; // error: 'I' is a protected member of 'B'
//std::cout << d.j; // error: 'j' is a protected member of 'X'
//std::cout << d.J; // error: 'J' is a protected member of 'X'
//std::cout << d.k; // error: 'k' is a protected member of 'D'
//std::cout << d.K; // error: 'K' is a protected member of 'D'
return 0;
}
我得出有关直接可及性的结论:2我的总结正确吗?
1我在C++ 17中使用了Clang 9.0.0编译器。
2对类
i
的成员B
的访问可以是直接的,即通过该类:b.i
(直接访问),也可以是间接的,即通过该类的派生类D
:d.i
(继承访问)。由于派生类继承的成员是该派生类的成员,且其可访问性发生了变化(参见[class.access/base-1]),因此对类成员的继承访问可以视为对该类派生类的继承成员的直接访问。换句话说,只需要考虑直接访问。3这里的My子句与标准[class.access/base-5.4]的引用子句略有不同:
这是因为编译器的行为有所不同,我的感觉是编译器是正确的。我认为该标准的条款存在两个问题:
d.*
中引发main
访问的错误来完成的工作); d.i
和d.I
中引发d.j
,d.J
,X::f
和g
访问错误而完成的工作,在程序中的i
中覆盖了I
,j
,J
和D
)。 最佳答案
如果您的问题基于访问权限,则这些是c++中的规则。我将在下面做一个基本的总结,但是对于详尽的解释,请转到here。这将更详细地介绍它们的工作原理。
要查看示例,请转到上面的链接。
使用嵌套类,您将处于该基类的范围之内,因此可以访问私有(private)成员和 protected 成员。如果成员是静态的,则您将可以直接访问,否则必须构造该类的对象才能访问该类中的那些成员。这是上面class X
的示例:
class X: public B {
public:
class A {
public:
void b() {
std::cout << J << std::endl;
std::cout << S << std::endl;
}
void d(X x) {
std::cout << x.j << std::endl;
std::cout << x.s << std::endl;
}
};
void f();
protected:
int j = 2;
static int const J = 2;
private:
friend void g();
int s = 3;
static int const S = 4;
};
这是将它们用于继承时公开, protected 和私有(private)的含义。
注意:派生类继承基类的所有方法,但以下情况除外。
现在关于 friend 说明符,这来自cpp引用here
在这里,您将获得示例以及有关如何使用它的详细说明。
当涉及到标准库时,您还将在其中找到有关许多信息的示例,还可以了解将来的标准以及编译器支持的功能。