我应该在带有模板的主题观察者模式中使用动态转换吗

2023-12-06

通过参考文章使用模板实现主题/观察者模式

template <class T>
class Observer
   {
   public:
      Observer() {}
      virtual ~Observer() {}
      virtual void update(T *subject)= 0;
   };

template <class T>
class Subject
   {
   public:
      Subject() {}
      virtual ~Subject() {}
      void attach (Observer<T> &observer)
         {
         m_observers.push_back(&observer);
         }
      void notify ()
         {
         std::vector<Observer<T> *>::iterator it;
         for (it=m_observers.begin();it!=m_observers.end();it++) 
              (*it)->update(static_cast<T *>(this));
         }
   private:
      std::vector<Observer<T> *> m_observers;
   };

我想知道而不是static_cast,我应该使用dynamic_cast?

这是因为如果我使用static_cast,在下面的情况下我会得到编译错误。

class Zoo : public Observer<Animal> {
public:
    Zoo() {
        animal = new Bird();
        animal->attach(this);
    }

    virtual ~Zoo() {
    delete animal;
    }

    virtual void update(Animal* subject) {
    }

    Animal* animal;
}

// If using static_cast, compilation error will happen here.
class Bird : public Animal, public Subject<Animal> {
public:
    virtual ~Bird() {
    }
}

使用有没有副作用dynamic_cast?


最好的肯定是根本不需要演员。你可以改变你的notify()函数,以便它接受正确的参数:

  void notify (T* obj)
     {
     std::vector<Observer<T> *>::iterator it;
     for (it=m_observers.begin();it!=m_observers.end();it++) 
          (*it)->update(obj);
     }

现在派生类可以传递正确的对象(this,如果适用的话),而基类不需要知道派生类与T.


按原样查看您的代码,static_cast依赖于这样一个事实:无论源自Observer,也将从作为模板参数传递的任何内容派生。我认为如果这不成立,它将在编译时被捕获,因为你不能static_cast from this to T*.

但是,您的代码非常接近称为“奇怪重复模板模式”的模式。为了使其完美契合,请将派生类的类型传递给Observer:

class Bird : public Subject<Bird> // note the template argument

现在你不需要从中派生Observer's T不再这样了,无论谁看到它(希望)都能识别该模式并更容易地理解代码。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我应该在带有模板的主题观察者模式中使用动态转换吗 的相关文章

随机推荐

  • Lotus Notes XPage 用于设计,Oracle(或其他 RDBMS)用于数据

    我计划使用 XPage 进行设计 加上 Lotus Notes Elements 来制作一个 Web 应用程序 但我不会将数据存储在 Lotus Notes 中 而是将数据存储在 RDBMS 特别是 Oracle 数据库 中 正如您所看到的
  • 如何在 Python 中检查文件大小?

    如何在Python中获取文件的大小 Use os path getsize gt gt gt import os gt gt gt os path getsize path to file mp3 2071611 输出以字节为单位
  • 我需要在添加新组件时动态调整 JPanel 的大小

    我需要让用户向我的 JFrame 添加更多文本字段 因此一旦框架的大小超过其原始值 滚动窗格就会介入 由于我无法将 JScrollPane 添加到 JFrame 以启用滚动 所以我决定将 JPanel 放在JFrame 并将 JPanel
  • Docker 身份验证:无法获取匿名令牌

    我的 gitlab 运行程序中出现以下错误 错误 授权失败 无法获取匿名令牌 获取 https auth ipv6 docker com token scope repository 3Alibrary 2Fnode 3Apull serv
  • std::async 和对象复制

    我正在尝试std async最终得到如下代码 class obj public int val obj int a val a cout lt lt new obj lt lt endl obj cout lt lt delete obj
  • XPath 中求和与积的聚合函数

    类似于这个问题 http stackoverflow com q 1333558 948404 我想使用XPath来计算结构中产品的总和 如下所示
  • 如何使R中的五大湖与海洋颜色相同?

    我刚开始使用 R 制作地图 我正在尝试制作北美地图 以美国为中心 并希望五大湖的颜色与海洋的颜色相同 我当前的代码默认使它们与国家 州具有相同的颜色 关于如何改变它们的颜色有什么想法吗 也许是不同的底图 当前代码 library cowpl
  • 对列表视图中的项目使用 setOnItemClickListener

    我有一个可以将音频保存在 SD 卡上的应用程序 我创建了一个列表视图 用于从 SD 卡检索文件名 我正在尝试设置一个侦听器 以便在单击文件名时我可以启动另一个播放该文件的意图 当我尝试设置监听器并传入一个新的OnItemClickListe
  • 背包C#实现任务

    我正在尝试在给定条件下编写背包 C 算法 但我总是遇到两个问题 我收到 索引超出数组范围 错误 或者我的结果仅为 0 我找到了几个 Knapsack 实现的代码示例 但无法弄清楚我做错了什么 代码示例 https www programmi
  • JS 库最佳实践:返回未定义或在错误的函数输入时抛出错误?

    当用 JavaScript 编写库时 处理函数无效输入的最标准 最友好 的方法是什么 我的直觉告诉我 返回 undefined 是完全可以的 但是抛出错误实际上更有帮助吗 还是真的不重要 我还可以看到返回 false null 甚至 1 但
  • 无法在 Windows 上使用 Android Studio 1.3.2 调试 NDK 示例

    我有Android Studio 1 3 2 NDK r10e gradle实验插件0 2 0 我已经克隆了ndk 样本仓库并仔细遵循以下说明NDK 预览 包括创建本机配置 当我选择 LLDB 作为调试器并调试 Teapot NDK 示例应
  • 在 webview 控件中显示本地 PDF 文件 - 显示空白 Pdf 文件

    我正在研究 Xamarin Forms UWP 我想在webview控件中显示本地PDF文件 我点击了这两个链接 https developer xamarin com recipes cross platform xamarin form
  • 右键单击停止传播

    如何停止 javascript 中右键单击事件的传播 以便父元素根本检测不到它们 当我单击以下 html 中的链接时 未检测到左键单击 但文档元素将右键单击检测为 单击 事件而不是 contextmenu 事件 我尝试将事件侦听器附加到 m
  • 如何才能完全禁用对assert()的调用?

    我的代码充满了对assert condition 在我使用的调试版本中g g这触发了我的断言 出乎意料的是 在我的发布版本中也触发了相同的断言 即没有编译的版本 g option 如何在编译时完全禁用断言 我应该明确定义NDEBUG在我生成
  • 具有 sql 转义的动态 mysql 查询是否与准备好的语句一样安全?

    我有一个应用程序 通过将动态 mysql 查询与 mysql mysqli 真实转义字符串结合使用 它将大大受益 如果我通过 mysql real escape 运行从用户收到的所有数据 它会和使用 mysql 准备好的语句一样安全吗 是的
  • 从 jQuery Mobile 重置值

    我需要重置我的页面的所有字段元素的值 这些元素是 输入 选择 组合框 复选框和单选组 搜索发现有如下代码 attr value input type checkbox attr checked false select each funct
  • 在 xslt 中添加一个或递增变量

    我想让计数器值根据条件递增 但我无法增加值或向全局变量加 1 我正在使用以下代码
  • Swift 扩展示例

    我本来想知道如何制作这样的东西 UIColor myCustomGreen 这样我就可以定义自己的颜色并在我的应用程序中使用它们 我之前研究过扩展 我认为我可能可以使用它们来解决我的问题 但我不记得到底如何设置扩展 在撰写本文时在 Goog
  • GAE (python) 中是否有与 Rails 的“flash”消息等效的东西?

    Ruby on Rails 有一种方法可以设置消息 例如flash notice and flash error 用户将在下一次机会看到 它对于在用户被重定向时 例如返回到登录页面 时通知用户登录失败等情况特别有用 在 Google App
  • 我应该在带有模板的主题观察者模式中使用动态转换吗

    通过参考文章使用模板实现主题 观察者模式 template