#include <iostream>
using namespace std;
class A
{
protected:
int a;
};
class B : public A
{
public:
int func(A* p)
{
cout << p->a;
}
};
我真的无法理解为什么我不能通过'p->a'访问'a'。
有没有一种方法可以在不将'protected'改为'public'的情况下访问类B中p的成员'a'?
#include <iostream>
using namespace std;
class A
{
protected:
int a;
};
class B : public A
{
public:
int func(A* p)
{
cout << p->a;
}
};
我真的无法理解为什么我不能通过'p->a'访问'a'。
有没有一种方法可以在不将'protected'改为'public'的情况下访问类B中p的成员'a'?
就这个问题而言,C++03标准如下(重点是我加的):
11.5 访问保护成员
1 当友元或派生类的成员函数引用基类的受保护的非静态成员函数或受保护的非静态数据成员时,在第11条款中描述的访问检查之外还会应用其他访问检查。除非形成成员指针 (5.3.1),否则访问必须通过指向派生类本身(或从该类派生的任何类的)的指针、引用或对象进行 (5.2.5)。
然而,你在这里尝试通过指向基类的指针进行访问,这是非法的。如果你将签名更改为
int func(B* p) // instead of A*
你会发现现在编译正常了。
这也是为什么你可以轻松地从class B
内部访问a
的原因:访问是通过隐式指针this
进行的,该指针的类型为B*
(即派生类)。如果你尝试这样做:
A* parent = static_cast<A*>(this);
int x = parent->a; // Does not compile!
由于同样的原因,你会发现它无法编译。
反之亦然:如果将指针p
向下转换为B*
,则可以很好地访问protected
成员:
class A
{
public:
// Added virtual destructor so that the class acquires a vptr,
// making dynamic_cast possible.
virtual ~A() {};
protected:
int a;
};
class B : public A
{
public:
int func(A* p)
{
// Now if we downcast p to B* we can access a just fine
// Of course if p does not actually point to a B, the
// program will have undefined behavior
int x = dynamic_cast<B*>(p)->a;
}
};
a
不同于p->a
,实际上你可以通过例如使用dynamic_cast<B*>(p)->a
从参数访问p->a
(尽管这会带来一套自己的问题集)。 - Jon哦,这是一个好问题。首先,让我说一下B
不是A
的朋友,因此不能通过“A”视图访问A
的私有(或受保护的)成员。即使我们在B
类的范围内,也不能随意查看A
的私有(或受保护的)成员。
然而,B
确实有一个a
。它可以访问它,因为它被声明为A
的受保护成员。但是,在B
中查看int a
的唯一方法是从对象的B
视图中获取它。
a
,那么您使用的编译器和操作系统是什么?在编译此代码时产生了什么消息? - rcollyera
,而不是p->a
吗? - wormsparty