C++ c++;将其自身强制转换为派生类后,是否可以访问基私有方法?

C++ c++;将其自身强制转换为派生类后,是否可以访问基私有方法?,c++,private,crtp,C++,Private,Crtp,我在使用CRTP(奇怪的重复模板模式)时发现了这一点 模板 阶级基础{ 私人: void f(){ //当T有自己的f()时,它调用 //当T没有时,它会调用自身,这是递归调用的 //但是我希望编译器在T没有自己的f()时会抱怨f()是私有的 静态_cast(this)->f(); } 公众: void g(){ f(); } }; 派生类:公共基{}; 我原以为我理解了公共、受保护和私人,但在这种情况下,看起来我错了。感谢您的解释 这仅在阴影声明为public时有效。见: 派生类:公共基{

我在使用CRTP(奇怪的重复模板模式)时发现了这一点

模板
阶级基础{
私人:
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() { }
          ^