C++ 静态_cast限制对公共成员函数的访问?

C++ 静态_cast限制对公共成员函数的访问?,c++,templates,inheritance,access-modifiers,static-cast,C++,Templates,Inheritance,Access Modifiers,Static Cast,在以下示例的静态_cast中,我得到了“error:'A'是'B'的不可访问基”: template<typename Derived> class A { protected: void funA() { static_cast<Derived *> (this)->funB(); } }; class B: protected A<B> { public: void funB() {} void funC() { funA(

在以下示例的静态_cast中,我得到了“error:'A'是'B'的不可访问基”:

template<typename Derived>
class A {
protected:
    void funA() { static_cast<Derived *> (this)->funB(); }
};

class B: protected A<B> {
public:
    void funB() {}
    void funC() { funA(); }
};

int main() {
    B().funC();
    return 0;
}
模板
甲级{
受保护的:
void funA(){static_cast(this)->funB();}
};
B类:受保护的A类{
公众:
void funB(){}
void funC(){funA();}
};
int main(){
B().funC();
返回0;
}
但是当使用reinterpret_cast或C风格类型cast((派生*)this)->funB()时,它编译/工作良好。这种行为正确吗

使用的编译器: gcc版本4.5.1 20100924(Red Hat 4.5.1-4)(gcc)


谢谢。

是的,看起来不错。您已经获得了受保护的继承,
A
不是从
B
派生的,也不是
B
的朋友,因此它无法看到
B
的基类来判断
static\u cast
是否有效。

受保护的和私有继承不会在类之间创建is关系,这是在类或其朋友之外执行
静态\u cast
所必需的。本质上,私有/受保护继承是实现的继承,而不是接口的继承。这就是为什么
static\u cast
不起作用的原因

我在以下示例的
static\u cast
中得到“error:'A'是'B'的不可访问基”:

template<typename Derived>
class A {
protected:
    void funA() { static_cast<Derived *> (this)->funB(); }
};

class B: protected A<B> {
public:
    void funB() {}
    void funC() { funA(); }
};

int main() {
    B().funC();
    return 0;
}
这是预期的:
B
派生自
A
,但此继承受到保护:只有
B
及其派生类可以使用
B
派生自
A
的事实

但当使用
重新解释cast
(…)时,它编译/运行良好。这种行为正确吗

这是意料之中的:
reinterpret\u cast
不关心继承或类型之间的其他关系

如果可能,
reinterpret\u cast
只会为您提供一个与原始指针值具有相同值(指向相同字节)的指针

这只是隐藏问题。

但是当使用(…)C样式的类型转换
((派生*)this)->funB()
时,它编译/工作得很好。这种行为正确吗

这是意料之中的:C样式强制转换忽略访问控制这只是隐藏问题。


解决方法是使
A
B
之间的继承关系可以在您想要使用它的地方访问。

C样式转换只允许编译器选择它认为最合适的转换。除了代码崩溃外,无法判断它是否选择了错误的强制转换@Neil C风格的cast在这里做了“正确”的事情,除了代码应该是固定的。@curiousguy但是如果B继承了多个类,那么它仍然会执行
重新解释cast
,这可能是错误的。@Neil错了,这个cast在建议的代码中没有执行
重新解释cast
。再一次:这个角色做得很对。@curiousguy很公平,我会投票支持你的答案。我没有提到friend,因为你不能将模板类型参数作为朋友,但当然你是对的,友谊是另一种方式,所以这没有问题。谢谢,更新了。谢谢大家,我明白了。我仍然怀疑我以前读过这方面的文章。如何正确解决这个问题?这取决于。每个类都应该知道
B
继承自
A
?如果是这样,请将继承公开。如果不是,正如Neil所说,让
A
成为
B
的朋友。因此我认为,对于这种模式,“受保护”不应该被使用-允许静态转换进行类型检查。为了隔离内部,可以使用protect从B中派生出另外一个类。“受保护继承和私有继承不会在类之间创建*是a*关系”,但显然是通过受保护或私有访问创建的。@curiousguy请在评论之前进行“尽职调查”,尤其是向下投票:,而不是is-a,“私有继承”是一种私有的继承,一点也不少,一点也不多。显然,它不是一种合成变体。这种胡说八道从何而来?@curiousguy“私人继承”是一种矛盾修饰法,一点也不少,一点也不多。在C++中,不要让它与继承类似。请按照我以前的消息链接到C++ FAQ,或者阅读Scott Meyers的一个特别好的链接项目34。看看其他的,可能也会有帮助。@curiousguy搜索“私人继承”也会给你带来一些。