试图在c ++中调用子类中父类的受保护函数

时间:2015-05-07 21:02:42

标签: c++ inheritance protected

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

#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类成为friend类的Parent,以避免前向声明,并尽可能地转发包含子类。另外,我不想让doStuff公开,因为在错误的情况下使用时,Parent的内部结构会非常混乱。

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

3 个答案:

答案 0 :(得分:3)

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

这仍然是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成员函数。

答案 1 :(得分:0)

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

答案 2 :(得分:-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;
}