我们可以找到here和here解释为什么我们不能从派生类中的方法调用基类对象的基类的受保护方法,如下代码所示:
class B {
protected:
void f ();
};
class D : public B {
public:
void g (B* other) {
other->f(); /* Error: B::f() is protected */
}
};
但有什么解决方案吗?如果我们真的想在这个对象上调用这个基本方法怎么办?毕竟,这样做不会有任何问题,我们可以确保other
真的是B
吗?
答案 0 :(得分:3)
注意:启用某些内容的直接(和推荐)方法是使继承的类成为基类的friend
;这意味着它可以访问protected
和private
部分。
我想稍微改变规则
所以你已经确定标准规定的规则令人讨厌,你想做任何你想做的事,你想要什么,以及你想要的方式!规则应该被打破等等。
class B {
protected:
void f ();
};
class D : public B {
public:
void g (B * other) {
(other->*&D::f) (); // legal
}
};
这个,合法且功能齐全的黑客如何运作?
即使标准规定我们不允许在B::f
内检查D
,但我们当然可以查看D::f
;这是相同的(继承的)事情,因为我们没有在f
内声明另一个D
。
我们的黑客一致认为D::f
的地址依赖于它的类型实际上是{em>指针到{em>成员函数的事实{ {1}},并使用此地址在B
上调用该函数。
编写代码片段的另一种(语义上)等效方式:
other
注意:从技术上讲,我们不会深入研究void (B::*hack)() = &D::f; (other->*hack) ();
的受保护内容,我们只是依赖于通过B
访问的内容发生的事实与D::f
中的那个相同。我们仍然遵守标准规定的规则,只是我们有点滥用它们。
答案 1 :(得分:0)
您可以class D
friend
class B
:
class B {
friend class D;
protected:
void f ();
};
答案 2 :(得分:0)
更好的解决方案是在Base中声明一个静态保护函数,将调用重定向到private / protected函数。这样,我们不会破坏封装,因为Base的设计者可以明确选择允许所有派生类相互调用foo,同时避免将foo放入公共接口或显式转换Base的所有可能子类成为朋友。