【问题标题】:How to access protected members in a derived class?如何访问派生类中的受保护成员?
【发布时间】:2023-03-18 04:15:01
【问题描述】:

来自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

给定:

您只能在您的类型的实例中访问受保护的成员(或 派生自您的类型)。您不能访问受保护的成员 父类或表亲类型的实例。

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

将构造函数更改为采用 Derived 实例也将解决 问题。

如何在不更改构造函数声明的情况下实现这一点?

【问题讨论】:

    标签: c++ inheritance


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      我认为你正在尝试做的事情应该是这样的:

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

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

      【讨论】:

      • +1。是的。 X::fun() 是从基类 X 访问隐藏名称的方法。不需要朋友或临时对象。
      • 这是一个完全不同的用例。这是在*this 上调用X::fun,而不是在X 类型的对象上调用它,该对象不是Y 对象的基类,这是问题中正在尝试的对象。
      • 我不明白这怎么能被接受为答案,就像@CharlesBailey 所说,这是一个完全不同的用例。
      【解决方案3】:

      看这个例子:

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

      这会产生

      从 Y20 从 X10

      因为您在 Y 中重载了 fun()-方法,如果您想通过调用 X::fun() 在 X 中调用 fun-方法,则必须向编译器提示您的意思。

      【讨论】:

        【解决方案4】:

        好吧,如果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】:

          在void Y::call()中

              X objX;
              objX.fun (); 
          

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

          您可以将XY 朋友作为@anycom 提供的解决方案。

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

          【讨论】:

          • this/current object of Y doesn't contains objX as it's base object 这句话是什么意思?
          • @AnishaKaul 每个对象都有一个指针this,它指向它自己,你已经知道了。 X 是 Y 的基类,那么 Y 的对象将包含类X 的子对象。在您的代码中Y 具有基类X,它可以在Y 的范围内访问它的基类 X only 的受保护/公共成员,但是无法访问对象X(您在代码中创建)的任何受保护/私有成员,就像您无法从main 访问Y 的私有成员一样
          【解决方案6】:

          您没有访问派生类中的受保护函数,而是试图重载它并从受保护提升到公共。这是禁止的操作,您只能隐藏派生类中的函数,例如将受保护的函数作为私有重载。

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

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

          或者像你这样称呼它objX.fun();也是正确的。

          【讨论】:

            猜你喜欢
            • 2018-11-27
            • 1970-01-01
            • 2014-08-27
            • 2013-10-21
            • 2015-01-17
            • 2018-04-17
            • 2015-12-30
            相关资源
            最近更新 更多