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

C++观察者模式:如何约束类对象避免被重新分配?

问题:如何约束C++类对象避免被重新分配?

在某些场景下(比如使用std::vector时),对象会被重新分配内存,这会给C++观察者模式的实现带来问题。

根据《四人帮》(Gang of Four)书籍中的定义,可观察对象的实现如下:

class ObservableSubject {
public:
  virtual ~ObservableSubject() = default;
  virtual void notify() = 0;

protected:
  ObservableSubject() = default;

private:
  std::vector<Observer*> mObservers;
};

Observer类的实现如下:

class Observer {
public:
  virtual ~Observer() = default;

  virtual void update(ObservableSubject& subject) = 0;

protected:
  Observer() = default;
};

考虑以下示例:

class Mapper final: public Observer  {};

当Mapper对象被存储在std::vector<Mapper>中时,一旦std::vector触发内存重新分配,mObservers中保存的指针就会失效。常规解决方案是改用指针(比如std::shared_ptr),用std::vector<std::shared_ptr<Mapper>>来存储,但这种方案要求开发者必须刻意避免让Mapper对象被重新分配,存在人为失误的隐患。

请问是否存在方法可以在C++中约束某个类,使其对象无法被重新分配?


解决方案:禁止类的拷贝与移动操作

对象被重新分配的核心原因是std::vector扩容时会执行拷贝/移动构造操作,将旧内存中的对象复制到新内存后销毁旧对象。因此,只要禁止类的拷贝和移动相关操作,就能从根源上阻止对象被重新分配。

具体实现方式

  • 显式删除特殊成员函数:在目标类中直接删除拷贝构造、拷贝赋值、移动构造、移动赋值这四个特殊成员函数,编译器会在尝试拷贝/移动对象时直接报错:

    class Mapper final: public Observer {
    public:
        // 禁止拷贝操作
        Mapper(const Mapper&) = delete;
        Mapper& operator=(const Mapper&) = delete;
        // 禁止移动操作
        Mapper(Mapper&&) = delete;
        Mapper& operator=(Mapper&&) = delete;
    };
    
  • 复用不可拷贝基类:定义一个通用的不可拷贝/移动基类,让需要约束的类继承它,避免重复编写代码:

    class NonRelocatable {
    public:
        NonRelocatable(const NonRelocatable&) = delete;
        NonRelocatable& operator=(const NonRelocatable&) = delete;
        NonRelocatable(NonRelocatable&&) = delete;
        NonRelocatable& operator=(NonRelocatable&&) = delete;
    protected:
        NonRelocatable() = default;
        ~NonRelocatable() = default;
    };
    
    class Mapper final: public Observer, public NonRelocatable {};
    

效果

当尝试将Mapper对象放入std::vector<Mapper>并触发扩容时,编译器会直接抛出错误——因为std::vector无法执行必要的移动/拷贝操作,从编译阶段就彻底阻止了对象被重新分配的可能。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 19:55:30