c++ - 使用模板和虚函数的技巧

标签 c++ templates

不久前,我了解了 Curiously Recurring Template Pattern ( http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern ),它让我想起了我用来实现事件队列缓存的技术。

基本思想是我们利用基类指针来存储同类指针类型的容器。但是因为Derived类是一个模板类,它存储了一个T类型的item,所以我们真正存储的是一个异构类型的列表。

我很好奇是否有人见过这种技术,这可能很有趣,如果是的话,是否有人为它命名?有人愿意批评它吗?有没有更好的方法来达到我的目的?

谢谢。

#include <iostream>
#include <algorithm>
#include <functional>
#include <list>
#include <string>

class Base
{
   public:
      Base(){}
      virtual ~Base(){}

      virtual void operator()() = 0;
};


template<typename C, typename T>
class Derived : public Base
{
   public:

      Derived(C* c, T item) : consumer_(c), item_(item) {}

      virtual void operator()()
      {
         consumer_->consume(item_);
      }

      C* consumer_;
      T item_;
};

class Consumer
{
      bool postpone_;
      std::list<Base*> cache_;


   public:
      Consumer() : postpone_(true)
      {
      }

      void pause()
      {
         postpone_ = true;
      }

      void resume()
      {
         postpone_ = false;

         const std::list<Base*>::iterator end = cache_.end();
         for ( std::list<Base*>::iterator iter = cache_.begin();
               iter != end;
               ++iter )
         {
            Base* bPtr = *iter;
            bPtr->operator()();
            delete bPtr;
         }
         cache_.clear();
      }

      void consume(int i) 
      {
         if ( postpone_ )
         {
            std::cerr << "Postpone int.\n";
            cache_.push_back(new Derived<Consumer, int>(this, i));
         }
         else
         {
            std::cerr << "Got int.\n";
         }
      }

      void consume(double d)
      {
         if ( postpone_ )
         {
            std::cerr << "Postpone double.\n";
            cache_.push_back(new Derived<Consumer, double>(this, d));
         }
         else
         {
            std::cerr << "Got double.\n";
         }
      }
      void consume(char c)
      {
         if ( postpone_ )
         {
            std::cerr << "Postpone char.\n";
            cache_.push_back(new Derived<Consumer, char>(this, c));
         }
         else
         {
            std::cerr << "Got char.\n";
         }
      }
};
static Consumer consumer;



void destroy(Base* object)
{
   delete object;
}


int main()
{
   // Consumer is registered with something that sends events out to lots
   // of different consumer types (think observer pattern). Also in the non-toy
   // version consumer isn't being passed PODs, but various Event types.
   consumer.consume(0);
   consumer.consume(0.1f);
   consumer.consume('x');

   consumer.resume();
}

输出是:

Postpone int.
Postpone double.
Postpone char.
Got int.
Got double.
Got char.

最佳答案

正如斯蒂芬在他的评论中指出的那样,您使用的是简单的多态性。当您在容器内部存储不同的对象时,您只能使用 Base 中定义的接口(interface)。也就是说,当然,除非您打算添加类型检查和向下转换以实际检索值。对于不相关的对象,您只能做有限的事情。

根据您实际想要实现的目标,您可能会考虑使用其他解决方案,例如 boost::any/boost::variant 如果您想要实际存储不相关的类型(在少数有意义的情况下——例如电子表格中的单元格)。

关于c++ - 使用模板和虚函数的技巧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3152415/

相关文章:

c++ - Qt 单个应用程序文件打开

c++ - 链接器错误 : UnResolved External Symbol Issue

c++ - 如何在C++中对称实现序列化和反序列化模板函数

C++ 模板函数自动静态? (不,他们不是)

javascript - Angular 指令 - 如何根据属性值选择模板?

c++ - 转换构造函数调用 move 但不调用 copy

c++ - 通过引用 C++ 中的构造函数传递堆栈分配的值

c++ - 在 VC++ 中解决 hid.lib "unresolved external symbol"链接器错误

c++ - 为什么别名模板给出冲突的声明?

javascript - 我该怎么做 <a href>?