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. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性