【问题标题】:trying to call protected function of parent class in child class in c++ [duplicate]试图在c ++中调用子类中父类的受保护函数[重复]
【发布时间】:2015-07-18 15:30:56
【问题描述】:

我一直以为我理解继承,但显然我不理解。我想从子类中调用同一父类的另一个实例的受保护成员函数,如以下示例代码所示:

#include <iostream>

class Parent {
protected:
  void doStuff(){
    std::cout << 5 << std::endl;
  }
};

class Child : public Parent {
public:
  void pubfunc(Parent* p){
    p->doStuff();
  }
};

int main(){
  Child* c = new Child();
  Parent* p = new Parent();
  c->pubfunc(p);
  return 0;
}

但是,此代码的编译失败并显示:

In member function ‘void Child::pubfunc(Parent*)’:
error: ‘void Parent::doStuff()’ is protected
error: within this context

我不想将Child 类设为Parent 类的friend,以避免前向声明和前向包含子类。另外,我不想公开doStuff,因为在错误的情况下使用它真的会弄乱Parent的内部结构。

为什么会发生这个错误,最优雅的解决方法是什么?

【问题讨论】:

  • 你传递的那个Parent不是你(这个)。因此,您无法访问它的父级受保护/私有接口。
  • 另外,你的设计有点奇怪。一个孩子是一个父母?也许BaseDerived 会是更好的名字。

标签: c++ inheritance protected


【解决方案1】:
class Parent 
{
protected:
    virtual void doStuff()
    {
        std::cout << 5 << std::endl;
    }
};

class Child : public Parent 
{
protected:  
    void doStuff() override
    {
        std::cout << 8 << std::endl;
    }

public:

    void pubfunc(Parent* p)
    {
        ((Child*)p)->doStuff();
    }
};

int main()
{
    Child* c = new Child();
    Parent* p = new Parent();
    c->pubfunc(p);      // will print 5
    c->pubfunc(c);      // will print 8
    return 0;
}

【讨论】:

  • Parent* 转换为Child*(未经任何检查)有潜在未定义行为的味道。
  • 是的,你是对的,回答很快,只是在编辑:)
  • 已编辑。我在一些罕见的场景中使用了上面的方法,例如,当对象的分层树必须提供加载和保存功能时,公众不能访问但相关对象可以访问。 Child 中的 doStuff 的覆盖当然不是必需的,因为它无论如何都会自动继承 Parent 的版本,就像示例一样。
【解决方案2】:

主要的问题是,如果 C++ 允许您直接访问基类指针的引用对象的非公共成员,那么您只需从公共基类派生即可轻松访问对象的数据。

这仍然是 C++ 类型系统中的一个已知漏洞,如下所示,您无需修改​​基类,也无需使用强制转换或类似的东西即可获得该访问权限。

在第三只手上,你应该做的是直接在基类中支持预期的用法,在基类中添加一个static 成员函数,如下所示:

#include <iostream>
using namespace std;

class Base
{
protected:
    void doStuff()
    {
        cout << 5 << endl;
    }

    static void doStuff( Base* p ) { p->doStuff(); }
};

class Derived : public Base
{
public:
    void pubfunc( Base* p )
    {
        doStuff( p );
    }
};

auto main() -> int
{
    Derived d;
    Base b;
    d.pubfunc( &b );
}

以我的拙见,这是最清晰和优雅的。

但为了完整起见,类型系统漏洞:

#include <iostream>
using namespace std;

class Base
{
protected:
    void doStuff()
    {
        cout << 5 << endl;
    }
};

class Derived : public Base
{
public:
    void pubfunc( Base* p )
    {
        (p->*&Derived::doStuff)();
    }
};

auto main() -> int
{
    Derived d;
    Base b;
    d.pubfunc( &b );
}

不过,我推荐static 成员函数。

【讨论】:

    【解决方案3】:

    受保护的成员可以在定义它们的类和从该类继承的类中访问。有时,当人们看到这种错误时,会感到困惑。但实际上您为 Parent 对象调用 doStuff 函数,它不会测量函数调用是否在继承类中完成。如果您从 main() 调用 doStuff 函数,结果将是相同的。

    【讨论】:

      猜你喜欢
      • 2012-06-04
      • 2010-11-27
      • 2012-08-28
      • 2011-09-22
      • 2013-02-04
      • 2020-10-02
      • 1970-01-01
      • 1970-01-01
      • 2021-02-16
      相关资源
      最近更新 更多