这是关于成员访问规则的正确摘要吗
Is this a correct summary on member access rules?
我正在努力完全理解C++标准[class.access]部分的多个段落中定义的成员访问规则。它们非常复杂,甚至令人困惑,因此我需要一个简短但准确而详尽的摘要。
我编译这个程序是为了测试受保护成员在几种情况下的可访问性(因为受保护成员的规则最复杂):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
任何实体都可以直接访问类的- 公共成员(参见[class.access/base-5.1])
- 一个类的私有成员只能由该类的成员和朋友直接访问(参见[class.access/base-5.2])
- 一个类的受保护成员只能由该类的成员和朋友直接访问(参见[class.access/base-5.3]),如果这些受保护成员是从这些基类或这些基类的基类继承的,则该类的基类的成员和友友可以直接访问(参考[class.address/base-5.4]),3和该类的派生类的成员(参见[class.access/base-5.3]),如果这些受保护的成员既不是非静态数据成员也不是非静态成员函数(参见[class.access/class.prected-1])
我的总结正确吗?
1我在C++17中使用了Clang 9.0.0编译器。
2对类B
的成员i
的访问可以是直接的,也就是通过该类:b.i
(直接访问),也可以是间接的,也可以通过该类的派生类D
:d.i
(heritage访问)。由于派生类继承的成员是其可访问性发生变化的派生类的成员(参见[class.access/base-1]),因此对类成员的继承访问可以被视为对该类派生类的继承成员的直接访问。换句话说,只需要考虑直接访问。
3我的子句与标准[class.access/base-5.4]的引用子句略有不同:
如果,则当在类N中命名时,成员m在点R可访问
- 存在在R处可访问的N的基类B,并且当在类B中命名时m在R处是可访问的
这是因为编译器的行为不同,我觉得编译器是对的。在我看来,该标准的条款有两个问题:
- 访问点R应限制为类B的成员和朋友(这是编译器通过在程序中的
main
中引发d.*
访问错误所做的) - 类N中的成员m应该被限制为从类B继承,而不是被类N重写(如果程序中的
D
中重写了i
、I
、j
和J
,编译器会通过在X::f
和g
中引发d.i
、d.I
、d.j
和d.J
访问的错误来完成这一操作)
如果您的问题是基于访问的,那么这些是c++中的规则。我将在下面做一个基本的总结,但要得到详尽的解释,请点击此处。这将更详细地介绍每种方法的工作原理。
public
类的公共成员可以在的任何位置访问受保护
1。致该班的成员和朋友
2。到该类的任何派生类的成员和朋友(直到C++17),但只有当访问受保护成员的对象的类是该派生类或该派生类的派生类时private
一个类的私有成员只能由该类的成员和朋友访问,无论这些成员是在同一个实例上还是在不同的实例上
要查看示例,请转到上面的链接。
有了嵌套类,您就在基类的范围内,所以私有和受保护的成员都可以访问。如果成员是静态的,则可以直接访问,否则必须构造该类的对象才能访问该类中的那些成员。下面是上面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;
};
以下是公共、受保护和私有在使用它们进行继承时的含义
public
当一个类使用公共成员访问说明符从基派生时,基类的所有公共成员都可以作为派生类的公共成员访问,并且基类的所有受保护成员都可以用作派生类的受保护成员访问(除非是好友,否则永远无法访问基的私有成员)protected
当一个类使用受保护成员访问说明符从基派生时,基类的所有公共和受保护成员都可以作为派生类的受保护成员进行访问(除非成为好友,否则永远无法访问基的私有成员)
private
当类使用私有成员访问说明符从基派生时,基类的所有公共成员和受保护成员都可以作为派生类的私有成员访问(除非是friended,否则永远无法访问基类的私有成员)。
注意:派生类继承基类的所有方法,但以下情况除外。
基类的构造函数、析构函数和复制构造函数重载运算符,如基类——这些运算符可能不会像您预期的那样起作用,并且应该以您为每个类的每个运算符重写的方式来实现。
基类的友元函数。
现在关于友元说明符,这来自这里的cpp引用在这里你将有关于如何使用它的例子和详细解释
当涉及到标准库时,您还可以在那里找到大量信息的示例,您还将能够看到标准将来会出现什么,以及编译器支持什么功能。
您错过了一个不那么直观的访问,c++依赖于编译,其中一个影响是的所有实例都是"相同的";并且如果该类上的函数可以接受"的引用,则可以访问彼此的私有变量;"他自己";,有关更多详细信息,请查看类变量CCD_ 20。
#include <iostream>
class MyClass{
int num = 69;
public:
void set_num(int n){
num = n;
};
int get_num() {
return num;
}
int get_num_from(MyClass * ptr_ref) {
return ptr_ref->num;
}
int get_num_from(MyClass ref) {
return ref.num;
}
};
int main(){
MyClass class_a;
MyClass class_b;
class_a.set_num(0);
std::cout << "class_a -> " << class_a.get_num() << std::endl;
std::cout << "class_b ref -> " << class_b.get_num_from(class_a) << std::endl;
std::cout << "class_b ptr_ref -> " << class_b.get_num_from(&class_a) << std::endl;
}
输出:
class_a -> 0
class_b ref -> 0
class_b ptr_ref -> 0
- 通过方法访问结构
- 使用不带参数的函数访问结构元素
- 如果我只是不访问queue_front节点的子节点,而是将它们推到队列中呢?还是BFS吗
- 用于访问容器<T>数据成员的正确 API
- 访问者访问变体并返回不同类型时出错
- 尝试通过多个向量访问变量时,向量下标超出范围
- 无法访问嵌套类.类的使用无效
- 写入位置0x0000000C时发生访问冲突
- 此代码是否违反一个定义规则
- 我们可以访问一个不存在的联盟的成员吗
- 这是关于成员访问规则的正确摘要吗
- 设置服务访问规则
- 在不违反严格的别名规则的情况下访问进程间共享内存中的对象
- 使用“alias()”解析精神规则时访问冲突
- 该"Named Constructor Idiom"似乎与静态方法无法访问非静态成员函数的规则相矛盾。有什么解释吗?
- as-if规则是否防止编译器对全局/成员变量的访问重新排序
- 如何在不违反严格的混叠规则的情况下访问内存映射的多字节寄存器
- 文件范围和访问规则
- 允许"this->"访问依赖基类成员的规则是什么?
- 一个关于类成员访问表达式的定义规则