C++ 在将模板 class 函数传递给另一个函数后无法调用它

C++ Unable to call template class function after passing it to another function

我有一个 Observable 模板。

template<typename T>
class Observable {

public:
  ~Observable() {
    observers.clear();
  }

  void registerObserver(const std::shared_ptr<Observer<T>> & observer) {
    observers.push_back(observer);
  }

  void update(const T & record) {
    for (auto &observer: observers) {
      observer->update(record);
    }
  }

private:
  std::list<std::shared_ptr<Observer<T>>> observers;
};

我的观察员也是从模板创建的:

class Observer {};

template<class T>
class Observer : public Observer {

public:
  virtual void update(const T record) = 0;
};

我运行这样的:

  auto cat = Cat() 
  auto catObservable = Observable<Cat>();
  auto catObserver = std::shared_ptr<CatObserver>(); // CatObserver is a derived class from Observer<Cat> 
  observable.registerObserver(catObserver);
  observable.update(cat);

此代码在调用 observer->update(record)Observable 模板中的 运行 时间有段错误。修复它的唯一方法是像这样进行动态转换:

  void update(const T & record) {
    for (auto &observer: observers) {
      std::shared_ptr<CatObserver> catObserver = std::dynamic_pointer_cast<CatObserver>(observer);
      catObserver->update(record);
    }
  }

我想要不同类型的观察者,我能想到的唯一方法是使用一个大的 if 语句或 switch 语句来尝试对所有观察者执行 dynamic_pointer_cast。这感觉就像代码的味道。

我是 C++ 的新手,甚至不确定这种类型的问题是否广为人知,我在这里尝试做的只是一种反模式。

有什么想法吗?

您正在插入空指针并将其推送到列表中:

// catObserver is nullptr
auto catObserver = std::shared_ptr<CatObserver>();

确实,就像创建一个没有参数的原始指针一样,它将为空:

CatObserver* rawCatObserver{}; // null

要实际创建一个 CatObserver,您必须调用 std::make_shared,它将进行动态分配:

// returns an allocated shared pointer
auto catObserver = std::make_shared<CatObserver>();

I'm new to C++ and not even sure if this type of a problem is well known and what I"m trying to do here is just an anti-pattern.

此代码没问题,但使用 std::list 迭代这些代码时性能可能会受到影响。对于您的用例,std::vector 可能更好。就个人而言,我尽量避免使用 std::unique_ptr,因为所有权更加明确。如果我可以用 std::function 和几个 lambda 表达式替换所有那些 类,我通常会倾向于那个。