gcc
__dynamic_cast (const void *src_ptr, // 对象指针
const __class_type_info *src_type, // 源类型
const __class_type_info *dst_type, // 目标类型,(the "T" in "dynamic_cast<T>(v)")
ptrdiff_t src2dst) // 偏移量,
{
// 检查指针是否为空
if (__builtin_expect(!src_ptr, 0))
return NULL; // Handle precondition violations gracefully.
// 虚函数表
const void *vtable = *static_cast <const void *const *> (src_ptr);
// 虚函数表头
const vtable_prefix *prefix =
(adjust_pointer <vtable_prefix>
(vtable, -ptrdiff_t (offsetof (vtable_prefix, origin))));
// 继承类
const void *whole_ptr =
adjust_pointer <void> (src_ptr, prefix->whole_object);
const __class_type_info *whole_type = prefix->whole_type;
__class_type_info::__dyncast_result result;
// 继承类的虚函数表
const void *whole_vtable = *static_cast <const void *const *> (whole_ptr);
const vtable_prefix *whole_prefix =
(adjust_pointer <vtable_prefix>
(whole_vtable, -ptrdiff_t (offsetof (vtable_prefix, origin))));
// src 是一个单独的基类,不能转成 dst
if (whole_prefix->whole_type != whole_type)
return NULL;
// 可以直接转换
if (src2dst >= 0
&& src2dst == -prefix->whole_object
&& *whole_type == *dst_type)
return const_cast <void *> (whole_ptr);
whole_type->__do_dyncast (src2dst, __class_type_info::__contained_public,
dst_type, whole_ptr, src_type, src_ptr, result);
if (!result.dst_ptr)
return NULL;
if (contained_public_p (result.dst2src))
// src 是 dst 的 public 基类
return const_cast <void *> (result.dst_ptr);
if (contained_public_p (__class_type_info::__sub_kind
(result.whole2src & result.whole2dst)))
// Both src and dst are known to be public bases of whole. Found a valid
// cross cast.
return const_cast <void *> (result.dst_ptr);
if (contained_nonvirtual_p (result.whole2src))
// Src is known to be a non-public nonvirtual base of whole, and not a
// base of dst. Found an invalid cross cast, which cannot also be a down
// cast
return NULL;
if (result.dst2src == __class_type_info::__unknown)
result.dst2src = dst_type->__find_public_src (src2dst, result.dst_ptr,
src_type, src_ptr);
if (contained_public_p (result.dst2src))
// Found a valid down cast
return const_cast <void *> (result.dst_ptr);
// Must be an invalid down cast, or the cross cast wasn't bettered
return NULL;
}
clang
__dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
const __class_type_info *dst_type,
std::ptrdiff_t src2dst_offset) {
// Possible future optimization: Take advantage of src2dst_offset
// Get (dynamic_ptr, dynamic_type) from static_ptr
void **vtable = *static_cast<void ** const *>(static_ptr);
ptrdiff_t offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
const __class_type_info* dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
// Initialize answer to nullptr. This will be changed from the search
// results if a non-null answer is found. Regardless, this is what will
// be returned.
const void* dst_ptr = 0;
// Initialize info struct for this search.
__dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};
// Find out if we can use a giant short cut in the search
if (is_equal(dynamic_type, dst_type, false))
{
// Using giant short cut. Add that information to info.
info.number_of_dst_type = 1;
// Do the search
dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
#ifdef _LIBCXX_DYNAMIC_FALLBACK
// The following if should always be false because we should definitely
// find (static_ptr, static_type), either on a public or private path
if (info.path_dst_ptr_to_static_ptr == unknown)
{
// We get here only if there is some kind of visibility problem
// in client code.
syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
"should have public visibility. At least one of them is hidden. %s"
", %s.\n", static_type->name(), dynamic_type->name());
// Redo the search comparing type_info's using strcmp
info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
info.number_of_dst_type = 1;
dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
}
#endif // _LIBCXX_DYNAMIC_FALLBACK
// Query the search.
if (info.path_dst_ptr_to_static_ptr == public_path)
dst_ptr = dynamic_ptr;
}
else
{
// Not using giant short cut. Do the search
dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
#ifdef _LIBCXX_DYNAMIC_FALLBACK
// The following if should always be false because we should definitely
// find (static_ptr, static_type), either on a public or private path
if (info.path_dst_ptr_to_static_ptr == unknown &&
info.path_dynamic_ptr_to_static_ptr == unknown)
{
syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
"has hidden visibility or is defined in more than one translation "
"unit. They should all have public visibility. "
"%s, %s, %s.\n", static_type->name(), dynamic_type->name(),
dst_type->name());
// Redo the search comparing type_info's using strcmp
info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
}
#endif // _LIBCXX_DYNAMIC_FALLBACK
// Query the search.
switch (info.number_to_static_ptr)
{
case 0:
if (info.number_to_dst_ptr == 1 &&
info.path_dynamic_ptr_to_static_ptr == public_path &&
info.path_dynamic_ptr_to_dst_ptr == public_path)
dst_ptr = info.dst_ptr_not_leading_to_static_ptr;
break;
case 1:
if (info.path_dst_ptr_to_static_ptr == public_path ||
(
info.number_to_dst_ptr == 0 &&
info.path_dynamic_ptr_to_static_ptr == public_path &&
info.path_dynamic_ptr_to_dst_ptr == public_path
)
)
dst_ptr = info.dst_ptr_leading_to_static_ptr;
break;
}
}
return const_cast<void*>(dst_ptr);
}
原文地址:http://www.cnblogs.com/miyanyan/p/16789112.html
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,请务用于商业用途!
3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员!
8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载
声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性