访问派生类中的受保护成员 昨天我遇到了一个错误,虽然很容易绕过,但我想确保我理解C++正确。

访问派生类中的受保护成员 昨天我遇到了一个错误,虽然很容易绕过,但我想确保我理解C++正确。,c++,C++,我有一个具有受保护成员的基类: class Base { protected: int b; public: void DoSomething(const Base& that) { b+=that.b; } }; 这个编译和工作都很好。现在我扩展了Base,但仍然希望使用b: class Derived : public Base { protected: int d; public: void DoSome

我有一个具有受保护成员的基类:

class Base
{
  protected:
    int b;
  public:
    void DoSomething(const Base& that)
    {
      b+=that.b;
    }
};
这个编译和工作都很好。现在我扩展了Base,但仍然希望使用b:

class Derived : public Base
{
  protected:
    int d;
  public:
    void DoSomething(const Base& that)
    {
      b+=that.b;
      d=0;
    }
};
注意,在这种情况下,
DoSomething
仍然引用
,而不是
派生
。我希望我仍然可以访问
派生的
中的
that.b
,但我得到了一个
无法访问受保护成员的
错误(MSVC 8.0-尚未尝试gcc)


显然,在
b
上添加公共getter解决了这个问题,但我想知道为什么我不能直接访问
b
。我认为当使用公共继承时,受保护的变量对派生类仍然可见。

类只能访问此类或派生类实例的受保护成员。它无法访问父类或表亲类实例的受保护成员

在您的情况下,
Derived
类只能访问
Derived
实例的
b
受保护成员,而不能访问
Base
实例的受保护成员


将构造函数更改为获取
派生的
实例将解决此问题。

您可以访问
派生的
的受保护成员,但不能访问
基的受保护成员(即使它是
派生的
受保护成员的唯一原因是因为它是从
基继承的)

如前所述,这就是语言的工作方式

另一种解决方案是利用继承并传递给父方法:

class Derived : public Base
{
  protected:
    int d;
  public:
    void DoSomething(const Base& that)
    {
      Base::DoSomething(that);
      d=0;
    }
};

使用
指针访问受保护的成员

class Derived : public Base
{
  protected:
    int d;
  public:
    void DoSomething(const Base& that)
    {
      this->b+=that.b;
      d=0;
    }
};

受保护的
成员可以访问:

  • 通过
    指针
  • 或相同类型的受保护成员(即使在基中声明)
  • 或者来自朋友类、函数
要解决您的问题,您可以使用最后两个选项之一

接受派生::DoSomething中的派生或将派生的
friend
声明为Base:

class Derived;

class Base
{
  friend class Derived;
  protected:
    int b;
  public:
    void DoSomething(const Base& that)
    {
      b+=that.b;
    }
};

class Derived : public Base
{
  protected:
    int d;
  public:
    void DoSomething(const Base& that)
    {
      b+=that.b;
      d=0;
    }
};

你也可以考虑一些公共吸气剂。< /P> < P>你可以尝试使用<强> STATICOSTCAST < const派生>(pBASE)-> Base::

class Derived : public Base
{
  protected:
    int d;
  public:
    void DoSomething()
    {
      b+=this->b;
      d=0;
    }
};

//this will work
class Base
{
  protected:
    int b;

  public:
    ...
};

class Derived : public Base
{
  protected:
    int d;

  public:
    void DoSomething(const Base& that)
    {
      b += static_cast<const Derived*>(&that)->Base::b;
      d=0;
    }
    void DoSomething(const Base* that)
    {
      b += static_cast<const Derived*>(that)->Base::b;
      d=0;
    }
};
类基
{
受保护的:
int b;
公众:
...
};
派生类:公共基
{
受保护的:
int d;
公众:
无效剂量测量(常数基和该)
{
b+=静态_cast(&that)->Base::b;
d=0;
}
无效剂量测量(常数基*该值)
{
b+=静态_cast(that)->Base::b;
d=0;
}
};
接下来,我编写了一个小代码,似乎可以解决访问派生类中受保护成员的问题

#include <iostream>

class B
{
protected:
    int a;
public:
    void dosmth()
    {
        a = 4;
    }

    void print() {std::cout<<"a="<<a<<std::endl;}
};

class D: private B
{
public:
    void dosmth(B &b)
    {
        b.*&D::a = 5;
    }
};

int main(int argc, const char * argv[]) {

    B b;
    D d;
    b.dosmth();
    b.print();
    d.dosmth(b);
    b.print();

    return 0;
}


在这个问题上,我举了一个糟糕的例子,但我不能称之为Base::DoSomething,因为DoSomething实际上在它进入派生类而不是基类时做的事情是不同的。请检查(注意:不要在生产代码中使用这些东西)。@AnishaKaul:您只能在您类型的实例中访问基类的受保护成员,不是表亲类型。例如,
按钮
无法从
文本框
上的
控件
访问受保护的属性
您只能在类型的实例中访问基类的受保护成员,而不能访问表亲类型
您再次编写了与上面编写的相同的语句。请看这里:@SLaks“将构造函数更改为获取派生实例也可以解决问题”是什么意思?@SLaks但为什么基类的实例可以访问该基类的其他实例的pivate成员?基类中的访问器方法如何,虚拟和受保护,您可以从派生类调用,并传递对基类或派生类的另一个实例的引用?这不起作用。考虑“您可以访问<代码>私下<代码>成员<代码>派生<代码>”和“继承的<代码>私下< /代码> <代码> Base<代码>的成员。这个答案是错误的。派生类无法访问基类的“b”,因为它被声明为受保护(这是用户首先要求的)。此代码将生成一个编译器错误。这是一个多么不正确的答案。问题在于
b
。添加
这个->
不仅是不相关的,而且是完全不可操作的,因为如果省略它,它是隐含的。我希望人们能对一种语言略知一二,并在将其作为答案发布之前测试他们编写的任何代码。这是有效的(至少在visual studio 2019中),我不知道为什么会被否决。如果
的动态类型不是(cv)
派生的
,但在这种情况下,b始终是基类的数据成员!或者更好,您可以使用:b+=static_cast(that)->Base::b;事实证明,我的示例与上面发布的示例几乎相同。我还想知道它是否有效。从我的观点来看,这可能会导致转换为派生类型,但我不确定。
a=4
a=5