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

C++中存储B实例或含B实例的C实例引用的方案咨询

可行的实现方案

1. 使用std::variant(C++17及以上)

这是最直接的惯用方案,利用标准库的变体类型存储两种可能的对象引用(避免值拷贝),再通过统一逻辑提取底层的B*。

示例代码:

#include <variant>
#include <functional>

// 目标存储类
struct D {
    // 存储B或C的引用,用std::reference_wrapper避免拷贝对象
    std::variant<std::reference_wrapper<B>, std::reference_wrapper<C>> target;

    // 统一获取底层B指针
    B* get_b() {
        return std::visit([](auto& val) -> B* {
            using T = std::decay_t<decltype(val.get())>;
            if constexpr (std::is_same_v<T, B>) {
                return &val.get();
            } else if constexpr (std::is_same_v<T, C>) {
                // 若需确保C的object指向B,可添加断言
                return static_cast<B*>(val.get().object);
            }
            return nullptr;
        }, target);
    }
};

// 使用示例
B b_inst;
C c_inst;
c_inst.object = &b_inst;

D d1;
d1.target = std::ref(b_inst);
D d2;
d2.target = std::ref(c_inst);

B* b_ptr1 = d1.get_b(); // 指向b_inst
B* b_ptr2 = d2.get_b(); // 指向c_inst中的b_inst

2. 自定义类型擦除接口

如果需要兼容C++17之前的版本,或者需要更灵活的扩展,可以抽象统一接口,为B和C分别实现适配器类。

示例代码:

#include <memory>

// 抽象访问接口,定义获取底层对象的行为
struct TargetAccessor {
    virtual ~TargetAccessor() = default;
    virtual B* get_b() = 0;
};

// B的适配器
struct BAccessor : TargetAccessor {
    B& b_obj;
    BAccessor(B& obj) : b_obj(obj) {}
    B* get_b() override { return &b_obj; }
};

// C的适配器
struct CAccessor : TargetAccessor {
    C& c_obj;
    CAccessor(C& obj) : c_obj(obj) {}
    B* get_b() override { return static_cast<B*>(c_obj.object); }
};

// 目标存储类
struct D {
    std::unique_ptr<TargetAccessor> accessor;

    // 支持直接传入B或C实例
    D(B& b) : accessor(std::make_unique<BAccessor>(b)) {}
    D(C& c) : accessor(std::make_unique<CAccessor>(c)) {}

    B* get_b() { return accessor->get_b(); }
};

3. 重新设计类结构的思路

如果上述方案不符合需求,可以考虑调整原有结构:

  • 把C中与object相关的逻辑抽离为独立组件,让B和该组件组合,而非让C持有A*;
  • 定义非侵入式 trait 模板,为B和C分别实现获取底层对象的逻辑,通过模板统一调用(类似标准库std::begin的模式)。

trait方式示例:

// 定义trait模板,默认无实现
template<typename T>
struct TargetTrait;

// 为B特化trait
template<>
struct TargetTrait<B> {
    static B* get(B& obj) { return &obj; }
};

// 为C特化trait
template<>
struct TargetTrait<C> {
    static B* get(C& obj) { return static_cast<B*>(obj.object); }
};

// 模板化的目标存储类
template<typename T>
struct D {
    T& target;
    B* get_b() { return TargetTrait<T>::get(target); }
};

// 使用示例
B b_inst;
C c_inst;
c_inst.object = &b_inst;

D<B> d1{b_inst};
D<C> d2{c_inst};

这种方式更轻量,但D会是模板类,若需要统一的非模板类型,前两种方案更合适。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 21:28:29