首页 > 解决方案 > 访问基类的受保护成员时相同的层次结构,不同的行为

问题描述

我在过去的考试中遇到了这段代码:

#include <iostream>
class cls1
{
protected:
    int x;

public:
    cls1()
    {
        x = 13;
    }
};
class cls2 : public cls1
{
    int y;

public:
    cls2()
    {
        y = 15;
    }
    int f(cls2 ob)
    {
        return (ob.x + ob.y);
    }
};
int main()
{
    cls2 ob;
    std::cout << ob.f(ob);
    return 0;
}

这工作得很好并且输出28。问题是,它似乎与此代码相矛盾(在另一项考试中发现):

#include <iostream>
class B
{
protected:
    int x;

public:
    B(int i = 28)
    {
        x = i;
    }
    virtual B f(B ob)
    {
        return x + ob.x + 1;
    }
    void afisare()
    {
        std::cout << x;
    }
};
class D : public B
{
public:
    D(int i = -32)
        : B(i)
    {
    }
    B f(B ob)
    {
        return x + ob.x - 1;/// int B::x is protected within this context
    }
};
int main()
{
    B *p1 = new D, *p2 = new B, *p3 = new B(p1->f(*p2));
    p3->afisare();
    return 0;
}

这是同一类型的层次结构,但一个可以访问ob.x而另一个不能。有人可以向我解释为什么会这样吗?

标签: c++inheritanceprotected

解决方案


不同之处在于,在第一种情况下,protected成员是通过派生类访问的。在第二种情况下,protected成员是通过基类访问的,这是不允许的。

对于protected会员

(强调我的)

类的protected成员只能访问

2)对该and friends (until C++17)类的任何派生类的成员,但仅当访问受保护成员的对象的类是该派生类或该派生类的派生类时

struct Base {
  protected:
    int i;
  private:
    void g(Base& b, struct Derived& d);
};

struct Derived : Base {
  void f(Base& b, Derived& d) { // member function of a derived class
    ++d.i;                      // OK: the type of d is Derived
    ++i;                        // OK: the type of the implied '*this' is Derived
//  ++b.i;                      // error: can't access a protected member through
                                // Base (otherwise it would be possible to change
                                // other derived classes, like a hypothetical
                                // Derived2, base implementation)
  }
};

推荐阅读