wco*_*ran 42 c++ inheritance protected
下面是访问实例的受保护字段x的一个微妙示例.B是A的子类,因此B类型的任何变量也是A类型.为什么B :: foo()可以访问b的x字段,而不是a的x字段?
class A {
protected:
int x;
};
class B : public A {
protected:
A *a;
B *b;
public:
void foo() {
int u = x; // OK : accessing inherited protected field x
int v = b->x; // OK : accessing b's protected field x
int w = a->x; // ERROR : accessing a's protected field x
}
};
Run Code Online (Sandbox Code Playgroud)
这是我用g ++得到的错误
$ g++ -c A.cpp
A.cpp: In member function ‘void B::foo()’:
A.cpp:3: error: ‘int A::x’ is protected
A.cpp:14: error: within this context
Run Code Online (Sandbox Code Playgroud)
Naw*_*waz 25
由于B
公开继承A
,A受保护的成员成为B的受保护成员,因此B可以像往常一样从其成员函数访问其受保护的成员.也就是说,对象B
可以B
从其成员函数访问受保护的成员.
但是使用类型的对象,不能在类外部访问A的受保护成员A
.
以下是标准(2003)的相关文字
11.5受保护的成员访问[class.protected]
当派生类的朋友或成员函数引用受保护的非静态成员函数或受保护的基类的非静态数据成员时,除了前面第11.102节中描述的那些之外,还应用访问检查.除非形成指向成员的指针(5.3) .1),访问必须通过指向,引用或派生类本身的对象(或从该类派生的任何类)(5.2.5).如果访问要形成指向成员的指针,则嵌套名称说明符应命名派生类(或从该类派生的任何类).
该示例遵循标准(2003)本身:
[Example:
class B {
protected:
int i;
static int j;
};
class D1 : public B {
};
class D2 : public B {
friend void fr(B*,D1*,D2*);
void mem(B*,D1*);
};
void fr(B* pb, D1* p1, D2* p2)
{
pb->i = 1; // ill-formed
p1->i = 2; // ill-formed
p2->i = 3; // OK (access through a D2)
p2->B::i = 4; // OK (access through a D2, even though naming class is B)
int B::* pmi_B = &B::i; // ill-formed
int B::* pmi_B2 = &D2::i; // OK (type of &D2::i is int B::*)
B::j = 5; // OK (because refers to static member)
D2::j =6; // OK (because refers to static member)
}
void D2::mem(B* pb, D1* p1)
{
pb->i = 1; // ill-formed
p1->i = 2; // ill-formed
i = 3; // OK (access through this)
B::i = 4; // OK (access through this, qualification ignored)
int B::* pmi_B = &B::i; // ill-formed
int B::* pmi_B2 = &D2::i; // OK
j = 5; // OK (because j refers to static member)
B::j = 6; // OK (because B::j refers to static member)
}
void g(B* pb, D1* p1, D2* p2)
{
pb->i = 1; // ill-formed
p1->i = 2; // ill-formed
p2->i = 3; // ill-formed
}
—end example]
Run Code Online (Sandbox Code Playgroud)
以上示例fr()
中的注释是友元函数D2
,mem()
是成员函数D2
,g()
既不是朋友,也不是成员函数.
Bil*_*eal 13
考虑:
class A {
protected:
int x;
};
class C : public A
{
};
class B : public A {
protected:
unique_ptr<A> a;
public:
B() : a(new C) // a now points to an instance of "C"
{ }
void foo() {
int w = a->x; // B accessing a protected member of a C? Oops.
}
};
Run Code Online (Sandbox Code Playgroud)
在公共继承中:
所有Public members
基类都成为Public Members
派生类,
所有Protected members
基类都成为Protected Members
派生类Derived Class
。
根据上述规则:
protected 成员x
成为A
class 的 protected 成员B
。
class B
可以在其成员函数中访问自己的受保护成员foo
,但只能访问A
派生它的成员,而不是所有A
类。
在这种情况下,class B
包含一个A
指针a
,它无法访问这个包含类的受保护成员。
为什么可以访问包含的指针B::foo()
的成员?class B
b
规则是:
在 C++ 中,访问控制基于每个类,而不是基于每个对象。
因此 的一个实例class B
始终可以访问另一个 的实例的所有成员class B
。
代码示例,演示了该规则:
#include<iostream>
class MyClass
{
public:
MyClass (const std::string& data) : mData(data)
{
}
const std::string& getData(const MyClass &instance) const
{
return instance.mData;
}
private:
std::string mData;
};
int main() {
MyClass a("Stack");
MyClass b("Overflow");
std::cout << "b via a = " << a.getData(b) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)