C++ c++;将其自身强制转换为派生类后,是否可以访问基私有方法?
我在使用CRTP(奇怪的重复模板模式)时发现了这一点C++ c++;将其自身强制转换为派生类后,是否可以访问基私有方法?,c++,private,crtp,C++,Private,Crtp,我在使用CRTP(奇怪的重复模板模式)时发现了这一点 模板 阶级基础{ 私人: void f(){ //当T有自己的f()时,它调用 //当T没有时,它会调用自身,这是递归调用的 //但是我希望编译器在T没有自己的f()时会抱怨f()是私有的 静态_cast(this)->f(); } 公众: void g(){ f(); } }; 派生类:公共基{}; 我原以为我理解了公共、受保护和私人,但在这种情况下,看起来我错了。感谢您的解释 这仅在阴影声明为public时有效。见: 派生类:公共基{
模板
阶级基础{
私人:
void f(){
//当T有自己的f()时,它调用
//当T没有时,它会调用自身,这是递归调用的
//但是我希望编译器在T没有自己的f()时会抱怨f()是私有的
静态_cast(this)->f();
}
公众:
void g(){
f();
}
};
派生类:公共基{};
我原以为我理解了
公共
、受保护
和私人
,但在这种情况下,看起来我错了。感谢您的解释 这仅在阴影声明为public
时有效。见:
派生类:公共基{
私人:
void f(){}
};
空x(导出*d){
d->g();
}
你会得到:
<source>: In instantiation of 'void Base<T>::f() [with T = Derived]':
<source>:13:9: required from 'void Base<T>::g() [with T = Derived]'
<source>:23:10: required from here
<source>:8:9: error: 'void Derived::f()' is private within this context
static_cast<T*>(this)->f();
^~~~~~~~~~~
<source>:19:10: note: declared private here
void f() { }
^
:在“void Base::f()[with T=Derived]”的实例化中:
:13:9:从“void Base::g()[带T=Derived]”中需要
:23:10:从这里开始需要
:8:9:错误:“void-Derived::f()”在此上下文中是私有的
静态_cast(this)->f();
^~~~~~~~~~~
:19:10:注意:此处声明为私有
void f(){}
^
如果函数未隐藏在派生的
中,则调用与this->Base::f()
相同,这必须是合法的,因为Base
是唯一可以访问它的类
您的困惑也可能来自访问一个看似不同的对象。请记住,访问修饰符按范围而不是实例限制访问。在
Base
中声明的任何方法都可以触及任何Base
实例的私有成员,而不仅仅是这个
。我想我理解如果你把private放在那里,它会触发投诉。让我困惑的是,在我将this
转换为Derived
类型之后,因为f()
是Derived
的私有方法,为什么它可以访问f()
?如果f()
在Derived
中定义为私有方法,那么它就不起作用,如示例所示。如果f()
没有阴影,则没有问题,因为f()
是Base
的私有成员<代码>派生的无法访问它:如果Base
无法访问,则任何东西都无法使用它。编译器静态地知道对象是派生的
,这一事实不会改变访问规则:否则,您可以通过将派生的
强制转换到基
来绕过该检查,这将不是非常有效的访问控制。感谢您的后续操作。但很抱歉,我还是不明白。1.你能不能帮我举个例子来解释一下,否则,你可以通过将你的派生代码转换成一个基来绕过这个检查,这将不是非常有效的访问控制?2.static_cast(this)->f()是如何实现的当派生的没有f()
时,code>与this->Base::f()
相同?对我来说,我们将在static_cast(this)
之后获得Derived
指针,因为它是Derived
类型,编译器应该检查f()
是否对此类型不可见,然后失败。@goldenretriever,通过包含CRTP,您的示例可能比您需要的更复杂;所有规则都适用于任何Base
和Derived:Base
类对。对于第1点:static\u cast(static\u cast(this))->f()
。对于第2点:Derived
不声明f()
,它的唯一声明是Base::f
,它可由Base
的任何成员访问Base::f()
不会仅仅因为继承而被“重命名”为Derivated::f()
:Derivated
毕竟不能访问f()
。@goldenretriever,static\u cast
不会更改所指向对象的性质。此外,访问控制不是由您试图访问的对象应用的:而是由作用域应用的。Base
的任何方法都可以访问Base
类的任何成员及其任何实例的任何成员。请注意不要使用CRTP,并让我知道它是否澄清了任何问题,或者它是否有助于您用不涉及CRTP的术语表述您的问题。
class Derived : public Base<Derived> {
private:
void f() { }
};
void x(Derived* d) {
d->g();
}
<source>: In instantiation of 'void Base<T>::f() [with T = Derived]':
<source>:13:9: required from 'void Base<T>::g() [with T = Derived]'
<source>:23:10: required from here
<source>:8:9: error: 'void Derived::f()' is private within this context
static_cast<T*>(this)->f();
^~~~~~~~~~~
<source>:19:10: note: declared private here
void f() { }
^