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

标签 c++ design-patterns

引用文章Implementing a Subject/Observer pattern with templates

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;
   };

我在想,我应该使用 dynamic_cast 而不是 static_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_castthisT* .

但是,您的代码非常接近于一种称为奇怪的重复模板模式的模式。为了使其完美匹配,将派生类的类型传递给 Observer:

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

现在您不再需要从 ObserverT 派生,无论谁(希望)看到它都能识别出模式并更容易理解代码。

关于c++ - 我应该在带有模板的主题观察者模式中使用动态转换吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3975624/

相关文章:

c# - 与 future 的 API 解耦——初学者发现需要依赖注入(inject)

c++ - 为什么为 union 或类似 union 的类删除了默认的默认构造函数?

Objective-C 类簇和私有(private)类初始化器

java - 这是装饰器设计模式的一个很好的例子吗?

c++ - 如何以依赖于模板类型名的方式提高 C++ 模板的精度?

c++ - 单例场景,重载不同参数的getInstance?

c - 用新字符串替换字符串模式

c++ - VS2010 调试级别不匹配

c++ - STD 分配器是否在堆上动态分配内存?它能安全地删除内存吗?

c++ - 基类静态引用数据成员上 C++ 对象切片行为的奇怪情况