【问题标题】:Accessing Inherited Functions访问继承的函数
【发布时间】:2019-03-18 07:56:04
【问题描述】:

在多重继承中,所有基类都包含具有不同功能的相同函数名,我们可以使用“::”范围解析运算符从特定基类访问受保护的函数。 但是,我尝试了其他方法。我在子类中创建了基类的对象。并尝试使用该特定类的对象调用该函数。 但我收到以下编译器错误: “‘void A::func(int&)’在此上下文中受到保护。” 请让我知道我哪里出错了。

 #include <iostream>
using namespace std;
class A
{
    protected:
        void func(int & a)
        {
            a = a * 2;
        }
};

class B
{
  protected:
        void func(int & a)
        {
            a = a * 3;
        }
};

class C
{
  protected:
        void func(int & a)
        {
            a = a * 5;
        }
};

 class D : public A,public B,public C {
     public: 
     int a;
     A a_val;
     B b_val;
     C c_val;
     void update_val(int new_val)
    {
     a = new_val;
     a_val.func(a);
     b_val.func(a);
     c_val.func(a);
     }
   void check(int); 
};

void D::check(int new_val)
{
    update_val(new_val);
    cout << "Value = " << a << endl;
};

int main()
{
    D d;
    int new_val;
    cin >> new_val;
    d.check(new_val);
}

【问题讨论】:

  • 其实这是一种方法,stackoverflow.com/questions/4672438/…可能更合适。
  • 如果你不需要它们,你从 A、B 和 C 继承了什么。从类派生并具有相同类型的成员通常没有多大意义。如果您使用与类本身不同类型的对象,则需要公共访问或友谊。那么,如果您想公开访问 func,为什么要对其进行保护呢?
  • A、B 和 C 类是您自己的代码还是您不想修改的一些外部库,这样您就不必在每次更新库或编译库时都修改库由供应商(无来源),如果更改不兼容,您可能希望避免未定义行为的风险。
  • 设计似乎完全错误。如果您从 A、B 和 C 继承,然后从 A、B 和 C 获得成员变量只是为了访问它们的受保护方法,请返回板并重新设计您的代码。这不好。非常糟糕。

标签: c++ c++11 inheritance protected access-specifier


【解决方案1】:

如果您想让您的代码与基类保持独立的功能并且仍然受到保护,解决问题的最简单方法是稍微更改受保护函数的名称并添加一个调用受保护成员的公共函数:例如,请参阅这些类声明:

class A {
public:
    void func( int& a ) {
        func_impl( a );
    }
protected:
    void func_impl( int& a ) {
        a = a * 2;
    }
};

class B {
public:
    void func( int& b ) {
        func_impl( b );
    }
protected:
    void func_impl( int& b ) {
        b = b * 3;
    }
};

class C {
public:
    void func( int& c ) {
        func_impl( c );
    }
protected:
    void func_impl( int& c ) {
        c = c * 5;
    }
};

class D : public A, public B, public C {
public:
    int a;
    A a_val;
    B b_val;
    C c_val;

    void update_val( int val ) {
        a = val;
        a_val.func( a );
        b_val.func( a );
        c_val.func( a );
    }

    void check( int );
};

void D::check( int val ) {
    update_val( val );
    std::cout << "Value = " << a << std::endl;
}

这提供了一个很好的公共接口来调用受保护的成员函数。这也解决了访问protected members 的问题。当我运行您的程序并输入值 5 时,它会返回 150 的结果并按预期工作。


这个 sn-p 应该向您展示继承是如何工作的,以及您何时可以访问和不能访问受保护的成员:

class DerivedA : public Base {
public:
    Base b;

    void call_message() {
        b.message(); // Protected Member of Base class can not be accessed
    }
};

class DerivedB : public Base {
public:
    void call_message() {
        message(); // This works without problem!
    }
};

正如我在上面所做的那样,解决此问题的一种方法是向受保护的实现添加一个公共接口调用程序。

class Base {
public:
    void message() {
        message_impl();
    }
protected:
    void message_impl() {
        std::cout << "This is a protected member of Base\n";
    }
};

现在你可以这样做了:

class DerivedA {
public:
    Base b;

    void call_message() {
        b.message();      // Accessible through public interface.
    }
};

【讨论】:

    【解决方案2】:

    当您在派生类中时,它可以访问自己的祖先方法。但它无权访问您的变量成员受保护和私有方法和变量。

    重新设计您的代码,您正在尝试一些事情并出于不好的原因扭曲其他类的设计。 Francis 的代码是一个很好的解决方案,但是D 不需要继承任何东西。

    【讨论】:

      【解决方案3】:

      如果你不想创建另一个函数,你可以这样做:

      #include <iostream>
      using namespace std;
      class A
      {
          protected:
              void func(int & a)
              {
                  a = a * 2;
              }
      };
      
      class B
      {
        protected:
              void func(int & a)
              {
                  a = a * 3;
              }
      };
      
      class C
      {
        protected:
              void func(int & a)
              {
                  a = a * 5;
              }
      };
      
       class D : public A,public B,public C {
           public: 
           int a;
           void update_val(int new_val)
          {
           a = new_val;
           this->A::func(a);
           this->B::func(a);
           this->C::func(a);
           }
         void check(int); 
      };
      
      void D::check(int new_val)
      {
          update_val(new_val);
          cout << "Value = " << a << endl;
      };
      
      int main()
      {
          D d;
          int new_val;
          cin >> new_val;
          d.check(new_val);
      }
      

      之所以有效,是因为this 引用了class D 的当前实例,并且它已经继承了class Aclass Bclass C。所以你可以直接访问各个类的受保护函数。

      记住:如果你没有继承类,它是行不通的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-01-07
        • 1970-01-01
        • 1970-01-01
        • 2015-04-23
        • 1970-01-01
        • 2021-07-24
        • 2017-09-05
        相关资源
        最近更新 更多