为什么C++需要公共继承,忽略朋友声明,才能使动态向下工作?
Why C++ requires public inheritance, ignoring friend declarations, to make dynamic downcast working?
这里我们有一个类B
,继承自类A
,它有一个friend
类C
。作为朋友,C
应该可以访问B
中的所有内容,包括A
基类。
为了测试它,
- 首先,我们创建一个
B
实例。 - 我们把它的地址改成一个
A*
- 然后我们尝试再次用
dynamic_cast<>
将其向下投射以B*
.
预期结果是取回原始B
实例的地址。
#include <cstdint>
#include <cstdio>
class A {
public:
virtual ~A() {};
};
class C;
class B : protected A { // <- this should be public to work! Why?
friend C;
};
class C {
public:
void doit() {
B *b = new B();
printf("b= %pn", b);
A *a = static_cast<A*>(b);
printf("a= %pn", a);
B *bb = dynamic_cast<B*>(a);
printf("bb=%pn", bb);
delete b;
};
};
int main() {
C c;
c.doit();
return 0;
};
类似情况下的常见问题,即基类必须是多态的(这里由其空的虚拟析构函数保证(,在这里得到了解决。
但是,动态转换仍然不起作用:bb
应该具有与b
相同的地址。
我的实验表明,如果A
是B
的public
基类,那么使其工作的唯一方法。但。。。C
是B
的朋友。即使protected
它也无法正常工作.
为什么会这样?
如果重要的话,我使用 gcc-8。
将"dynamic_cast"视为全局函数。 "朋友C;"将友谊交给"C类"而不是"dynamic_cast"。
成员访问检查在编译时进行。
dynamic_cast检查运行时的基本可访问性。RTTI 具有基本的可访问性信息(请参阅 MS 实现 rtti.cpp; __RTDynamicCast(,但没有友谊。
总结评论中的有用信息和引用资源,可以写一个自我答案。
首先,friend
声明是没有问题的:friend
仅影响声明它的类的成员的可访问性,而不影响其基类。
其次,可访问性签入C++进入编译时间。但是dynamic_cast
的可访问性检查发生在运行时。这种可访问性检查的限制要严格得多,并且只有在继承public
时才能发生dynamic_cast
。
其可能的原因是,正确执行此操作可能需要针对不同的访问级别使用不同的 rtti 表。
相关文章:
- C++为线程工作动态地分割例程
- 声明C++具有动态大小的数组类型在 Linux 中工作正常,但不能在 Windows 中工作
- 为什么C++需要公共继承,忽略朋友声明,才能使动态向下工作?
- 为什么重载运算符"="动态数组的类上无法正常工作?C++
- C++:检查动态取消分配是否正常工作
- 为什么必须动态分配扩展数组才能使此功能正常工作C++
- 如果类数组中的向量是动态push_backed的,内存如何工作
- C 编程,动态内存无法使用Malloc和Calloc正常工作
- 快速排序动态大量对象无法正常工作
- 可以作为固定大小(堆栈)和动态大小(堆)工作的数组封装程序
- 在打印出动态分配的数组中的前两个数字时遇到问题,其他数字工作正常
- OpenCL:动态内存分配,是使用空闲工作项更好还是同时写入更好
- C++动态内存分配未按预期工作
- 如何设计一个配置实用程序来静态和动态链接工作
- 动态内存复制是如何工作的
- 动态分配的工作线程在几分钟后泄漏,尽管它不应该
- 动态链接是如何工作的,它的用法以及如何以及为什么要制作dylib
- 以下代码是如何工作的(从DLL加载动态类)
- 动态内存分配是如何工作的
- 我应该使用静态工作池还是动态工作池(线程)