info

関数ポインタを使ったお手軽なStrategyパターン

Rubyによるデザインパターン」にのってるコードをC++に翻訳中
関数ポインタつかうと、いろいろpublicにしなきゃならんのね

Report.hpp

#include <string>
#include <vector>

using namespace std;

class Report
{
 public:
  Report (void (*)(Report&));
  void output_report ();
  string title;
  vector<string> text;

 private:
  void (*formatter)(Report&);
};

Report.cpp

#include <string>
#include <vector>
#include "Report.hpp"

Report::Report (void (*fn)(Report&))
{
  title = "月次報告";
  text.push_back ("順調");
  text.push_back ("最高の調子");

  formatter = fn;
}

void Report::output_report ()
{
  (*formatter)(*this);
}

stra.cpp

#include "Report.hpp"

#include <iostream>
#include <string>
#include <vector>

void plaintextformatter (Report &context)
{
  cout << "*** " + context.title + " ***" << endl;
  for (vector<string>::iterator line = context.text.begin (); line != context.text.end (); ++line)
    {
      cout << *line << endl;
    }
}

void htmlformatter (Report &context)
{
  cout << "<html>" << endl;
  cout << "  <head>" << endl;
  cout << "    <title>" + context.title + "</title>" << endl;
  cout << "  </head>" << endl;
  cout << " <body>" << endl;
  for (vector<string>::iterator line = context.text.begin (); line != context.text.end (); ++line)
    {
      cout << "    <p>" + *line + "</p>" << endl;
    }
  cout << "  </body>" << endl;
  cout << "</html>" << endl;
}

int main (int args, char *argv[])
{
  Report *htmlreport = new Report (htmlformatter);
  Report *textreport = new Report (plaintextformatter);
#ifdef HTML
  htmlreport->output_report ();
#endif /*HTML*/

#ifdef TEXT
  textreport->output_report ();
#endif /*TEXT*/

  delete htmlreport;
  delete textreport;
}