私有范围内私有继承的动态向下转型
对我遇到的这个问题进行了调整。考虑一下:
class A {};
class B : private A {
static void foo();
};
void B::foo(){
B* bPtr1 = new B;
A* aPtr1 = dynamic_cast<A*>(bPtr1); // gives pointer
B* bPtr2 = dynamic_cast<B*>(aPtr1); // gives NULL
}
由于 aPtr1
实际上是 B*
类型,并且我们已经完全访问 B
及其从 B
的继承。 code>A,我希望这两个转换都能工作。但他们没有;为什么?还有其他方法可以实现这个演员阵容吗?
请注意:
- 如果 foo() 不是 B 的成员,则两次转换都会失败。
- 如果
B
公开继承自A
,则两种强制转换都将起作用。
A tweak on this question that I've run into. Consider:
class A {};
class B : private A {
static void foo();
};
void B::foo(){
B* bPtr1 = new B;
A* aPtr1 = dynamic_cast<A*>(bPtr1); // gives pointer
B* bPtr2 = dynamic_cast<B*>(aPtr1); // gives NULL
}
Since aPtr1
is, in fact, of type B*
, and since we've got full access to B
and its inheritance from A
, I'd expected both casts to work. But they don't; why? Is there another way to achieve this cast?
Note that:
- If
foo()
were not a member of B, both casts would fail. - If
B
inherits fromA
publicly, both casts would work.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
5.2.7(ISO/IEC 14882,12/29/2003)在这一点上非常明确:
(回想一下 11.2 “如果基类的一个发明的公共成员是可访问的,则称基类是可访问的。”) 。
这解释了为什么第一个演员阵容有效。现在,第二个:
因此,您观察到的行为似乎是由于
private
继承造成的:即使基类是可访问的,它也不是 public,并且标准要求 public ,无法访问。很烦人不是吗?我手边没有 C++0x 草案,也许有人可以用其中的引号编辑我的答案,以防情况发生变化。
这取决于你想做什么。基本上,私有继承只是执行组合的另一种方法。如果您确实要返回指向私有派生实例的指针,那么要么将继承设为公共,要么返回一个成员。
不管怎样,你会很高兴知道
static_cast
似乎没有这个限制:因此,如果您确定指针的实际动态类型是什么,则可以在
foo
内进行static_cast
。我对有关为什么存在这种不一致的任何其他信息感兴趣。
5.2.7 (ISO/IEC 14882, 12/29/2003) is pretty explicit on this point:
(recall 11.2 "A base class is said to be accessible if an invented public member of the base class is accessible.").
This explains why the first cast works. Now, for the second:
So it seems that the behavior you observe is due to the
private
inheritance: even if the base class is accessible, it is not public, and the standard requires public, not accessible.Annoying, isn't it ? I don't have the C++0x draft handy, perhaps someone can edit my answer with quotes from it, in case things have changed.
It depends on what you want to do. Basically, private inheritance is just another device for performing composition. If you really are to return a pointer to the private derived instance, then either make the inheritance public, or return a member.
Anyways, you'll happy to know that
static_cast
doesn't seem to have this limitation:so if you know for sure what the actual dynamic type of the pointer is, you are allowed to
static_cast
insidefoo
.I'd be interested in any additional information about why this inconsistency exists.
它们不起作用,因为 A 中没有虚函数。当您进行向下转换时,这很简单 - 编译器可能甚至懒得进行检查。当您进行向上转换时,编译器必须进行检查,但它仅定义为在您具有虚拟函数时才起作用。如果不这样做,编译器将无法进行检查,结果为
NULL
。继承保护级别和其他可访问性问题与问题正交,并且它们仅存在于编译时,如果程序编译则它们可以正常工作。
那不是真的。
foo()
与 RTTI 功能完全没有关系 - 它不是虚拟的,甚至不是实例成员。如果 B 公开继承 A,那么 A 仍然没有虚函数,并且仍然无法工作。They don't work because there's no virtual functions in A. When you do the downcast then that's trivial- the compiler probably doesn't even bother making a check. When you make an upcast then the compiler must check, but it's only defined to work when you have virtual functions. When you don't, then the compiler will fail to make the check and the result is
NULL
.The inheritance protection level and other accessibility issues are orthogonal to the problem, and they only exist at compile-time, if the program compiles then they work fine.
That's just not true.
foo()
has absolutely no bearing on RTTI functionality- it's not virtual and it's not even an instance member. If B inherits from A publicly- then A still has no virtual functions and it still won't work.