带有受保护字段的微妙 C++ 继承错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6986798/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
subtle C++ inheritance error with protected fields
提问by wcochran
Below is a subtle example of accessing an instance's protected field x. B is a subclass of A so any variable of type B is also of type A. Why can B::foo() access b's x field, but not a's x field?
下面是一个访问实例的受保护字段 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
}
};
Here is the error I get with g++
这是我用 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
回答by Nawaz
Since B
is publicly inherited from A
, A's protected member(s) become B's protected member(s), so B can access its protected members as usual from its member function(s). That is, the objects of B
can access the protected members of B
from its member functions.
由于B
是从 公开继承的A
,A 的受保护成员成为 B 的受保护成员,因此 B 可以像往常一样从其成员函数访问其受保护成员。也就是说, 的对象B
可以B
从其成员函数访问受保护的成员。
But A's protected members cannot be accessed outside the class, using object of type A
.
但是 A 的受保护成员不能在类外使用类型的对象访问A
。
Here is the relevant text from the Standard (2003)
这是标准(2003)中的相关文本
11.5 Protected member access [class.protected]
When a friend or a member function of a derived class references a protected nonstatic member function or protected nonstatic data member of a base class, an access check applies in addition to those described earlier in clause 11.102) Except when forming a pointer to member (5.3.1), the access must be through a pointer to, reference to, or object of the derived class itself (or any class derived from that class)(5.2.5). If the access is to form a pointer to member, the nested-name-specifier shall name the derived class (or any class derived from that class).
11.5 受保护的成员访问 [class.protected]
当派生类的友元或成员函数引用基类的受保护非静态成员函数或受保护非静态数据成员时,除了在第 11.102 节中描述的那些之外,还应用访问检查,除非形成指向成员的指针 (5.3 .1),必须通过派生类本身(或从该类派生的任何类)的指针、引用或对象进行访问(5.2.5)。如果访问要形成一个指向成员的指针,则嵌套名称说明符应命名派生类(或从该类派生的任何类)。
And the example follows from the Standard (2003) itself as:
这个例子来自标准(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]
Note in the above example fr()
is a friend function of D2
, mem()
is a member function of D2
, and g()
is neither a friend, nor a member function.
注意上例中fr()
是 的友元函数D2
,mem()
是 的成员函数D2
,g()
既不是友元函数,也不是成员函数。
回答by Billy ONeal
Consider:
考虑:
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.
}
};
回答by Alok Save
In Public Inheritance:
All Public members
of the Base Classbecome Public Members
of the derived class&
All Protected members
of the Base Classbecome Protected Members
of the Derived Class
.
在公有继承:
所有Public members
的的基类成为Public Members
了的派生类和
所有Protected members
的的基类成为Protected Members
的Derived Class
。
As per the above rule:
protected member x
from A
becomes protected member of class B
.
根据上述规则:
受保护的成员x
fromA
成为受保护的成员 class B
。
class B
can access its own protected members in its member function foo
but it can only access members of A
through which it was derived not all A
classes.
class B
可以在其成员函数中访问它自己的受保护成员,foo
但它只能访问A
派生它的成员,而不是所有A
类。
In this case, class B
contains a A
pointer a
, It cannot access the protected members of this contained class.
在这种情况下,class B
包含一个A
指针a
,它不能访问这个包含类的受保护成员。
Why can the B::foo()
access the members of the contained class B
pointer b
?
为什么可以B::foo()
访问包含class B
指针的成员b
?
The rule is:
In C++ access control works on per-class basis, not on per-object basis.
So an instance of class B
will always have access to all the members of another instance of class B
.
规则是:
在 C++ 中,访问控制基于每个类,而不是基于每个对象。
因此, 的实例class B
将始终可以访问 的另一个实例的所有成员class B
。
An Code Sample, which demonstrates the rule:
一个代码示例,它演示了规则:
#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;
}
回答by firyice
Why can B::foo() access b's x field, but not a's x field?
为什么 B::foo() 可以访问 b 的 x 字段,而不能访问 a 的 x 字段?
A protected member can only be accessed by other members of the same class (or derived classes).
受保护的成员只能被同一类(或派生类)的其他成员访问。
b->x
points to a protected member of an instance of class B (through inheritance), so B::foo()
can access it.
b->x
指向类 B 实例的受保护成员(通过继承),因此B::foo()
可以访问它。
a->x
points to a protected member of an instance of class A, so B::foo()
cannot access it.
a->x
指向类 A 实例的受保护成员,因此B::foo()
无法访问它。
回答by mac
Lets start with basic concept,
让我们从基本概念开始,
class A {
protected:
int x;
};
class B : public A {
public:
void foo() {
int u = x; // OK : accessing inherited protected field
}
};
Since child is inheriting parent, child gets x. Hence you can access x directly in foo() method of child. This is the concept of protected variables. You can access protected variables of parent in child directly. Note : Here I am saying you can access x directly but not through A's object! Whats the difference ? Since, x is protected, you cannot access A's protected objects outside A. Doesnt matter where it is - If its main or Child . That's why you are not able to access in the following way
由于孩子继承父母,孩子得到x。因此,您可以直接在 child 的 foo() 方法中访问 x。这就是受保护变量的概念。您可以直接访问 child 中 parent 的 protected 变量。注意:这里我是说您可以直接访问 x 但不能通过 A 的对象访问!有什么不同 ?由于 x 受保护,因此您无法访问 A 之外的 A 受保护对象。无论它在哪里 - 如果它的 main 或 Child 。这就是您无法通过以下方式访问的原因
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
}
};
Here comes an interesting concept. You can access a private variable of a class using its object with in the class!
这里有一个有趣的概念。您可以使用类中的对象访问类的私有变量!
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.
}
};
//Same is for protected variables.Hence you are able to access the following example.
//对于受保护的变量也是如此。因此您可以访问以下示例。
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
}
};
Hope it explains :)
希望它解释:)
C++ is complete Object Oriented Programming, where as Java is pure Object oriented :)
C++ 是完整的面向对象编程,而 Java 是纯面向对象的 :)
回答by Kerrek SB
Class B
is not identical to class A
. That's why members of class B
cannot access non-public members of class A
.
ClassB
与 class 不同A
。这就是为什么 class 的成员B
不能访问class 的非公共成员A
。
On the other hand, class B
derivespublicly from class A
, so class B
now has a (protected) member x
which any member of class B
can access.
另一方面, class从 class 公开B
派生A
,因此 classB
现在有一个(受保护的)成员x
, class 的任何成员都B
可以访问该成员。