访问实例外部的函数指针

时间:2012-07-18 20:20:14

标签: c++ function-pointers

我有一个如下所述的课程:

class InputReader 
{  
public:
  typedef void (*handler)(std::string, int);
  static void errorHandler(std::string error, int severity); //Supplies a default error handler
  static void warningHandler(std::string error, int severity); //Supplies a default warning handler
  handler errorH;
  handler warningH;

  InputReader(std::string pwd = "", handler eHandler = errorHandler, handler wHandler = warningHandler);

  bool readFile(std::string filename);
  std::vector<first> mesh;
  //other irrelevant objects that need to be read into
};

first是一个结构:

struct first
{
  std::string filename;
  double scale;
};

Mooing Duck的帮助下,我有:

std::istream& operator>>(std::istream& file, first& obj) 
{
  std::string symbol;
  while(file >> symbol) 
  {
    if (symbol[0] == '#') 
    {
      std::getline(file, symbol);
    } 
    else if (symbol == FIRSTTAGEND) 
    {
      break;
    }
    else if (symbol == FILEPATH) 
    {
      if (!(file >> '=' >> obj.filename))
        std::cerr << symbol << " is incorrectly formatted"; //This needs to use errorH
    } 
    else if (symbol == SCALE) 
    {
      if (! (file >> '=' >> obj.scale) )
        std::cerr << symbol << " is incorrectly formatted"; //This needs to use errorH
    } 
    else 
    { //not a member: failure
      std::cerr << symbol << " is not a member of first";
      file.setstate(file.rdstate() | std::ios::badbit);
      break;
    }
  }
  return file;
}

std::istream& operator>>(std::istream& file, InputReader& obj) 
{
  std::string symbol;
  while(file >> symbol) 
  {
    if (symbol[0] == '#') 
    {
      std::getline(file, symbol);
    } 
    else if (symbol == FIRSTTAGBEG) 
    {
      first t;
      if (file >> t)
        obj.mesh.push_back(t);
    } 
    else 
    {
      obj.errorH(symbol + " is not a member of the input reader.", 1);
      file.setstate(file.rdstate() | std::ios::badbit);
    }
  }
  return file;
}

bool InputReader::readFile(std::string filename)
{
  std::ifstream infile;
  infile.open(filename.c_str());
  infile >> *this;
  return true;
}
在构造InputReader对象时设置

errorH。它可以由类的用户提供,否则,它使用我提供的默认值。唯一的问题是,当errorH被读入时,我无法访问first。我该如何解决这个问题?

问题限制:不允许使用外部库。不允许使用C ++ 11 / C ++ OX。

3 个答案:

答案 0 :(得分:4)

你自然没有多少选择:

  1. 不要使用>>运算符并创建一个执行相同但接受三个参数的函数 - 输入流,first对象和输入阅读器对象。
  2. 定义接受>>first元组作为第二个参数(即一对指针)的运算符InputReader。例如:std::istream& operator>>(std::istream& file, std::pair<first *, InputReader *> & obj)
  3. 只要你有很好的想象力,你就可以无限期地扩展这个列表。

    希望它有所帮助。

    更新:

    这是一个简单的例子:

    #include <string>
    #include <vector>
    #include <fstream>
    #include <iostream>
    
    struct first {
        std::string filename;
        double scale;
    };
    
    class InputReader {
      public:
        typedef void (*handler)(const std::string &, int);
    
        InputReader(const std::string & pwd = std::string(),
                    handler eHandler = errorHandler,
                    handler wHandler = warningHandler);
    
        bool readFile(const std::string & filename);
    
        static void errorHandler(const std::string & error, int severity);
        static void warningHandler(const std::string & error, int severity);
    
        handler errorH;
        handler warningH;
        first firstobj;
        std::vector<first> mesh;
    };
    
    std::istream & operator >> (std::istream & file,
                                std::pair<first, InputReader *> & obj)
    {
        std::string symbol;
        while (file >> symbol) {
            if (symbol[0] == '#') {
                std::getline(file, symbol);
            } else if (symbol == "FIRSTTAGEND") {
                break;
            } else if (symbol == "FILEPATH") {
                if (!(file >> obj.first.filename))
                    obj.second->errorHandler(symbol + " is incorrectly formatted",
                                             1);
            } else if (symbol == "SCALE") {
                if (!(file >> obj.first.scale))
                    obj.second->errorHandler(symbol + " is incorrectly formatted",
                                             1);
            } else { //not a member: failure
                std::cerr << symbol << " is not a member of first";
                file.setstate(file.rdstate() | std::ios::badbit);
                break;
            }
        }
        return file;
    }
    
    std::istream & operator>>(std::istream & file, InputReader & obj)
    {
        std::string symbol;
    
        while (file >> symbol) {
            if (symbol[0] == '#') {
                std::getline(file, symbol);
            } else if (symbol == "FIRSTTAGBEG") {
                std::pair<first, InputReader *> t(first(), &obj);
                if (file >> t)
                    obj.mesh.push_back(t.first);
            } else {
                obj.errorH(symbol + " is not a member of the input reader.", 1);
                file.setstate(file.rdstate() | std::ios::badbit);
            }
        }
        return file;
    }
    
    bool InputReader::readFile(const std::string & filename)
    {
        std::ifstream infile;
        infile.open(filename.c_str());
        infile >> *this;
        return true;
    }
    

答案 1 :(得分:2)

弗拉德提出了一个有趣的想法,但我并不喜欢使用std::pair<first, InputReader *>,因为那不是我想要阅读的类型。我会稍微改变你目前的设计。将流读取函数移动到单独的函数,该函数接受流引用,以及您需要的任何其他变量,并让流操作符调用该成员。当您希望操作员可以访问可选的附加参数时,通常会使用此想法

std::istream& loadObjectFromFile(std::istream& file, 
              first& obj,
              handler errorH=InputReader::errorHandler, 
              handler warningH=InputReader::warningHandler); //new
std::istream& operator>>(std::istream& file, first& obj)
{return loadObjectFromFile(file, obj);}

然后实现阅读器功能,是直接复制粘贴,除了现在你还有错误处理程序

std::istream& loadObjectFromFile(std::istream& file, first& obj
                                    handler errorH, handler warningH) {
  ...
    else if (symbol == FILEPATH) 
    {
      if (!(file >> '=' >> obj.filename))
        errorH(symbol + " is incorrectly formatted.", 1); //new
    } 
    else if (symbol == SCALE) 
    {
      if (! (file >> '=' >> obj.scale) )
        errorH(symbol + " is incorrectly formatted.", 1); //new
    } 
    else 
    { //not a member: failure
      errorH(symbol + " is not a member of first.", 1); //new
      file.setstate(file.rdstate() | std::ios::badbit);
      break;
    }
  }
  return file;
}

然后,InputReader的相应更改是istream函数

std::istream& operator>>(std::istream& file, InputReader& obj) 
{
    ...
    else if (symbol == FIRSTTAGBEG) 
    {
      first t;
      if (loadObjectFromFile(file, obj))
        mesh.push_back(t);
    } 
    ...
}

答案 2 :(得分:1)

std::istream& operator>>(std::istream& file, first& obj)替换为std::istream &InputReader::readObj(std::istream &file, first &obj)

另外,为了保持一致性,请将std::istream& operator>>(std::istream& file, InputReader& obj)替换为std::istream &InputReader::readFileStream(std::istream& file)

然后在readFileStream中,你可以写if (readObj(file, t)),在readObj你可以写  errorH("oops", -1)