C++简单继承问题

5
#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'?


1
据我所知,您应该能够访问 a,那么您使用的编译器和操作系统是什么?在编译此代码时产生了什么消息? - rcollyer
你可以直接访问 a,而不是 p->a 吗? - wormsparty
错误 C2248:“A::a”:无法访问类“A”中声明的受保护成员。 - Jaebum
我目前正在使用Visual Studio 2010... - Jaebum
3个回答

10

就这个问题而言,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;
    }
};

非常感谢Jon!!C++比我之前想象的更有趣了 :) - Jaebum

2
使用`p->a`只能访问A类中的公共变量。由于`a`是受保护的变量,在类B中继承了它,因此应该使用`cout<
我认为你可以通过将类B设为友元类来使用`cout<a`。
或者像Jon指出的那样,使用指向B类而不是A类的指针。

似乎friend也不起作用:(我尝试了#include <iostream> using namespace std; class A { protected: int a;}; class B : public A { friend class A; public: int func(A* p) { cout << p->a; }}; - Jaebum
正好相反:类A: {友元类B; ...} - djeidot
没有变量的公共和受保护的“版本”。编译器不允许您通过指向基类的指针访问非公共成员。 - Jon
@djeidot:答案仍然是误导性和不完整的。a不同于p->a,实际上你可以通过例如使用dynamic_cast<B*>(p)->a从参数访问p->a(尽管这会带来一套自己的问题集)。 - Jon

1

哦,这是一个好问题。首先,让我说一下B不是A的朋友,因此不能通过“A”视图访问A的私有(或受保护的)成员。即使我们在B类的范围内,也不能随意查看A的私有(或受保护的)成员。

然而,B确实有一个a。它可以访问它,因为它被声明为A的受保护成员。但是,在B中查看int a的唯一方法是从对象的B视图中获取它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接