You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++如何编译期检查派生类向上转型到基类是否需要指针调整

编译期判断向上转型是否需要指针调整的实现方案

结论

可以实现,非虚继承场景下基类子对象的偏移是编译期常量,仅需判断该偏移是否为0即可。虚继承场景下基类偏移量运行时动态确定,无法编译期获取。

你示例中Clang能判定printf的输出结果,本质就是编译器在编译期就确定了基类偏移量是常量,我们的实现就是直接提取这个编译器已知的常量值。

实现方案

方案1:C++20 标准无扩展实现

仅要求C++20及以上标准,无编译器依赖,适用标准布局类型:

#include <type_traits>

template <typename Derived, typename Base>
requires std::is_base_of_v<Base, Derived> && std::is_standard_layout_v<Derived>
struct needs_upcast_adjustment {
    static constexpr bool value = []() consteval {
        Derived d{};
        const Derived* pd = &d;
        const Base* pb = pd;
        return reinterpret_cast<const char*>(pb) != reinterpret_cast<const char*>(pd);
    }();
};

template <typename Derived, typename Base>
constexpr bool needs_upcast_adjustment_v = needs_upcast_adjustment<Derived, Base>::value;

方案2:编译器扩展实现(兼容C++11及以上)

主流编译器均提供内置扩展可直接获取基类子对象偏移,不受标准布局限制:

  • GCC/Clang 环境:
template <typename Derived, typename Base>
constexpr bool needs_upcast_adjustment_v = __builtin_offsetof(Derived, Base) != 0;
  • MSVC 环境:
template <typename Derived, typename Base>
constexpr bool needs_upcast_adjustment_v = __offsetof_base(Derived, Base) != 0;

测试验证

用你给出的示例类验证,静态断言可直接编译期通过:

struct A { int a; };
struct B { int b; };
struct C : A, B { int c; };

// 验证C转A不需要调整
static_assert(!needs_upcast_adjustment_v<C, A>);
// 验证C转B需要调整
static_assert(needs_upcast_adjustment_v<C, B>);

内容的提问来源于stack exchange,提问作者dragonroot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 21:21:03