以下是访问实例的受保护字段x的一个微妙示例。 B是A的子类,因此类型B的任何变量也是A类。 为什么B :: foo()可以访问b的x字段,但不能访问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
}
};
这是我用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
答案 0 :(得分:25)
由于B
是从A
公开继承的,因此受保护的成员成为B的受保护成员,因此B可以像往常一样从其成员函数访问其受保护成员。也就是说,B
的对象可以从其成员函数访问B
的受保护成员。
但是,使用A
类型的对象,无法在课堂外访问受保护的成员。
以下是标准(2003)
的相关文字11.5受保护的成员访问[class.protected]
当派生类的朋友或成员函数引用受保护的非静态成员函数或受保护的基类的非静态数据成员时,除了前面第11.102节中描述的那些之外,还应用访问检查。除非形成指向member(5.3.1),访问必须通过指向,引用或派生类本身的对象(或从该类派生的任何类)(5.2.5)。如果访问要形成指向成员的指针,则nested-name-specifier应命名派生类(或任何名称) 从该类派生的类)。
这个例子来自标准(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]
在上面的例子中注意fr()
是D2
的朋友函数,mem()
是D2
的成员函数,g()
不是朋友,也不是会员职能。
答案 1 :(得分:12)
考虑一下:
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.
}
};
答案 2 :(得分:3)
在公共继承中:
基类的所有Public members
成为派生类的Public Members
&amp;
基类的所有Protected members
都成为Protected Members
的{{1}}。
按照上述规则:
来自Derived Class
的受保护成员x
成为班级A
的受保护成员。
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;
}
答案 3 :(得分:1)
为什么B :: foo()可以访问b的x字段,但不能访问x字段?
受保护的成员只能由同一类(或派生类)的其他成员访问。
b->x
指向B类实例的受保护成员(通过继承),因此B::foo()
可以访问它。
a->x
指向A类实例的受保护成员,因此B::foo()
无法访问它。
答案 4 :(得分:0)
班级B
与班级A
不同。这就是为什么班级B
的成员无法访问班级A
的非公开成员。
另一方面,课程B
从课程A
公开,因此课程B
现在有一个(受保护的)成员x
班级B
的任何成员都可以访问。
答案 5 :(得分:0)
让我们从基本概念开始,
class A {
protected:
int x;
};
class B : public A {
public:
void foo() {
int u = x; // OK : accessing inherited protected field
}
};
由于孩子继承父母,孩子得x。因此,您可以直接在子的foo()方法中访问x。这是受保护变量的概念。您可以直接访问子级中父级的受保护变量。 注意:我在这里说你可以直接访问x而不是通过A的对象!有什么不同 ?由于x受到保护,因此无法访问A外的A受保护对象。无论它在哪里 - 如果它的主要或儿童。这就是您无法以下列方式访问的原因
class B : public A {
protected:
A *a;
public:
void foo() {
int u = x; // OK : accessing inherited protected field x
int w = a->x; // ERROR : accessing a's protected field x
}
};
这是一个有趣的概念。您可以在类中使用其对象访问类的私有变量!
class dummy {
private :
int x;
public:
void foo() {
dummy *d;
int y = d->x; // Even though x is private, still you can access x from object of d - But only with in this class. You cannot do the same outside the class.
}
};
//同样适用于受保护的变量。您可以访问以下示例。
class B : public A {
protected:
A *a;
B *b;
public:
void foo() {
int u = x; // OK : accessing inherited protected field x
int y = b->x; // OK : accessing b's protected field x
int w = a->x; // ERROR : accessing a's protected field x
}
};
希望它解释:)
C ++是完整的面向对象编程,其中Java是纯面向对象的:)