访问派生类中的受保护成员

时间:2010-07-14 15:20:28

标签: 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 DoSomething(const Base& that)
    {
      b+=that.b;
      d=0;
    }
};

请注意,在这种情况下,DoSomething仍在引用Base,而不是Derived。我希望我仍然可以访问that.b内的Derived,但我收到cannot access protected member错误(MSVC 8.0 - 还没有尝试过gcc)。

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

7 个答案:

答案 0 :(得分:40)

您只能访问类型实例中的受保护成员(或从您的类型派生) 您无法访问父级或堂兄类型实例的受保护成员。

在您的情况下,Derived类只能访问b实例的Derived成员,而不能访问其他Base实例。

更改构造函数以获取Derived实例也将解决问题。

答案 1 :(得分:4)

如上所述,这就是语言的运作方式。

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

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

答案 2 :(得分:3)

您可以访问Derived的受保护成员,但不能访问Base的成员(即使它是Derived受保护成员的唯一原因是因为它继承自Base }})

答案 3 :(得分:3)

可以访问

protected个成员:

  • 通过this指针
  • 或相同类型的受保护成员,即使在基础
  • 中声明
  • 或来自朋友类,职能

要解决您的情况,您可以使用最后两个选项之一。

在Derived :: 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;
    }
};

在某些情况下,您也可以考虑使用公共吸气剂。

答案 4 :(得分:1)

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

//this will work

答案 5 :(得分:1)

hack for stl之后,我写了一个小代码,似乎解决了在派生类中访问受保护成员的问题

#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;
}

打印

a=4
a=5

答案 6 :(得分:0)

您可以尝试使用 static_cast (pBase)-> Base :: protected_member ...

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;
    }
};