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

时间:2012-02-04 09:29:09

标签: c++ inheritance

来自http://www.parashift.com/c++-faq-lite/basics-of-inheritance.html#faq-19.5

  

在类的受保护部分中声明的成员(数据成员或成员函数)只能由该类的成员函数和朋友以及成员函数和派生类的朋友访问

那么,在派生类中访问受保护函数fun的方法是什么?

#include <iostream>
using namespace std;

class X
{
    private:
        int var;
    protected:
        void fun () 
        {
            var = 10;
            cout << "\nFrom X" << var; 
        }
};

class Y : public X
{
    private:
        int var;
    public:
        void fun () 
        {
            var = 20;
            cout << "\nFrom Y" << var;
        }

        void call ()
        {
            fun ();

            X objX;
            objX.fun ();
        }
};

这导致:

anisha@linux-dopx:~/> g++ type.cpp
type.cpp: In member function ‘void Y::call()’:
type.cpp:9:8: error: ‘void X::fun()’ is protected
type.cpp:32:14: error: within this context

我看到了这个:Accessing protected members in a derived class

假设:

  

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

     

在您的情况下,Derived类只能访问a的b成员   派生实例,而不是不同的Base实例。

     

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

如何在不更改构造函数声明的情况下完成此操作?

6 个答案:

答案 0 :(得分:6)

一种解决方案是将friend class Y添加到X。

答案 1 :(得分:6)

我认为你想要做的事情应该是这样的:

#include <iostream>
using namespace std;

class X
{
    private:
        int var;
protected:
    virtual void fun () 
    {
        var = 10;
        cout << "\nFrom X" << var; 
    }
};

class Y : public X
{
private:
    int var;
public:
    virtual void fun () 
    {
        var = 20;
        cout << "\nFrom Y" << var;
    }

    void call ()
    {
        fun ();


        X::fun ();
    }
};

这样你就可以从你的基类调用hiden成员了。否则你必须添加朋友X,因为它在其他帖子中被指出。

答案 2 :(得分:2)

见这个例子:

#include <iostream>
using namespace std;

class X {
  private:
    int var;
  protected:
    void fun () 
    {
      var = 10;
      cout << "\nFrom X" << var; 
    }
};

class Y : public X {
  private:
    int var;
  public:
    void fun () 
    {
      var = 20;
      cout << "\nFrom Y" << var;
    }

    void call ()
    {
      fun(); /* call to Y::fun() */
      X::fun (); /* call to X::fun() */

      X objX;
      /* this will not compile, because fun is protected in X        
      objX.fun (); */

    }
};

int main(int argc, char ** argv)  {
  Y y;
  y.call();
  return 0;  
}

这会产生

From Y20
From X10

因为您在Y中重载了fun() - 方法,所以如果要通过调用{{1来调用X中的fun - 方法,则必须给编译器一个提示。 }}

答案 3 :(得分:1)

在void Y :: call()

    X objX;
    objX.fun (); 

//这里你试图访问受保护的objX成员,this / Y的当前对象不包含objX作为它的基础对象,它们都是不同的对象。这就是您无法访问其成员的原因。

你可以让Y的{​​{1}}朋友作为@anycom提供的解决方案。

编辑:我的意思是,从X内部(继承自Y),您可以简单地调用“它的”基类的受保护/公共成员X即您只是简单地访问它的基本成员。但这并不意味着您现在可以访问X类型的所有对象的受保护成员,因为您尝试从类X的外部范围访问这些成员,即通过{{1的对象}}。你知道所有这些规则,但似乎你做了太多的思考0_o

答案 4 :(得分:1)

好吧,如果friend没问题,那么这个角度也可以。

#include <iostream>

class X {
private:
    int var;
protected:
    virtual void fun() {
        var = 10;
        std::cout << "\nFrom X" << var;
    }

    static void Fun(X& x) {
        x.fun();
    }
};

class Y : public X {
private:
    int var;
public:
    virtual void fun() {
        var = 20;
        std::cout << "\nFrom Y" << var;
    }

    void call() {
        fun();
        X objX;
        objX.fun(); /* << ne-ne */
        Fun(objX); /* << ok */
    }
};

当然,如果按原样使用,请注意传递给X::Fun的类型。

答案 5 :(得分:-1)

您没有在派生类中访问受保护的函数,您正试图使其超载并从受保护升级到公共。这是一个禁止的动作,你只能隐藏派生类中的函数,例如过载保护功能作为私人。

访问受保护的函数意味着从类的某个成员调用它:

class Y : public X
{
public:
    void call() {
      fun();
    }
}

或者像objX.fun();所说的那样也是正确的。