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

C++类层次结构中跨类的布尔状态处理问题

问题描述

现有如下类层次结构:模板具体类A、模板抽象类B以及接口C,继承关系为 A <-- B <-- C。其中B声明了函数:

virtual std::optional<T> foo() const = 0;

C声明了函数:

virtual bar() = 0;

这两个函数均在A中完成了恰当的定义。

代码中存在一个B类型对象列表,会对其调用foo();同时存在一个C*指针列表,会对其调用bar()。

示例代码与需求

注:原示例代码存在语法错误,已修正(补充模板声明、函数返回值等)

template <typename T>
class A : public B<T>
{
public: 
    std::optional<T> foo() const override { /*...*/ };
    void bar() override { /*...*/ };

    // ...
};

template <typename T>
class B : public C
{
public: 
    virtual std::optional<T> foo() const = 0;

    // ...
};

class C
{
public: 
    virtual void bar() = 0;
};

需要为该类层次结构的对象添加一个布尔状态,具体需求如下:

  1. 需要一个布尔状态m_isInteresting,属于整个类层次结构代表的对象。
  2. 由于解耦需求,不希望将m_isInteresting放在A中。
  3. 调用foo()时需将m_isInteresting设为true。
  4. 调用bar()时需将m_isInteresting设为false。

已尝试方案

  • 为C创建装饰器包装类,包含m_isInteresting成员及相应访问器,转发bar()方法,在其中调用C的bar()并将m_isInteresting设为false,但无法将其设为true,因为foo()在下层类中。
  • 尝试将foo()的声明移至C(定义仍保留在A中),但因该函数返回std::optional<T>,而C并非模板类,派生类函数签名需与基类匹配,此方案难以实现。
  • 考虑为B和C分别创建装饰器类,共享外部存储的m_isInteresting,但此方案过于繁琐复杂。

解决方案

方案一:将状态放在顶层基类C中,通过保护接口修改

把状态放在最顶层的C类中,添加protected的状态修改方法,让下层类在实现对应函数时调用:

class C
{
protected:
    mutable bool m_isInteresting = false;
    void setIsInteresting(bool value) const { m_isInteresting = value; }
public: 
    virtual void bar() = 0;
    // 若外部需要访问状态,可添加getter
    bool isInteresting() const { return m_isInteresting; }
};

template <typename T>
class B : public C
{
public: 
    virtual std::optional<T> foo() const = 0;

    // ...
};

template <typename T>
class A : public B<T>
{
public: 
    std::optional<T> foo() const override { 
        this->setIsInteresting(true);
        /*...原有逻辑...*/
    };
    void bar() override { 
        this->setIsInteresting(false);
        /*...原有逻辑...*/
    };

    // ...
};

mutable修饰符让const成员函数foo()也能修改状态,避免了const_cast的使用,同时状态属于整个对象,符合需求。

方案二:用Mixin类注入状态与行为

如果不想修改原有C类的定义,可以创建一个Mixin类,通过多重继承将状态和修改逻辑注入到类层次中:

class InterestStateMixin
{
protected:
    mutable bool m_isInteresting = false;
    void markAsInteresting() const { m_isInteresting = true; }
    void markAsUninteresting() { m_isInteresting = false; }
public:
    bool isInteresting() const { return m_isInteresting; }
};

// 修改B类,同时继承C和Mixin
template <typename T>
class B : public C, public InterestStateMixin
{
public: 
    virtual std::optional<T> foo() const = 0;

    // ...
};

template <typename T>
class A : public B<T>
{
public: 
    std::optional<T> foo() const override { 
        this->markAsInteresting();
        /*...原有逻辑...*/
    };
    void bar() override { 
        this->markAsUninteresting();
        /*...原有逻辑...*/
    };

    // ...
};

这种方式无需改动原有C类,通过Mixin实现状态注入,同时满足解耦要求,状态不属于A类。

方案三:模板装饰器覆盖全接口

针对之前装饰器方案的缺陷,创建模板装饰器类,同时实现B的接口,这样既能处理foo()也能处理bar():

template <typename T>
class DecoratedB : public B<T>
{
private:
    B<T>* m_wrapped;
    bool m_isInteresting = false;
public:
    DecoratedB(B<T>* wrapped) : m_wrapped(wrapped) {}

    std::optional<T> foo() const override {
        m_isInteresting = true;
        return m_wrapped->foo();
    }

    void bar() override {
        m_isInteresting = false;
        m_wrapped->bar();
    }

    bool isInteresting() const { return m_isInteresting; }
};

使用时将原B对象包装成DecoratedB,无论是通过B调用foo()还是通过C*调用bar()(DecoratedB继承自B,而B继承自C),都会触发状态修改,无需维护两个独立装饰器。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 11:13:21