简体   繁体   English

访问实例外部的函数指针

[英]Access function pointers outside of the instance

I have a class as outlined below: 我有一个如下所述的课程:

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 is a struct: first是结构:

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

With Mooing Duck 's help I have: 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;
}

errorH gets set upon construction of the InputReader object. errorH顺利通过建设InputReader对象的设定。 It can be provided by the user of the class, otherwise, it uses the default ones I provide. 它可以由类的用户提供,否则,它使用我提供的默认值。 The only problem is that I can't access errorH when first is being read into. 唯一的问题是,在firsterrorH我无法访问errorH How can I solve this? 我怎么解决这个问题?

Problem constraints: External libraries are not allowed. 问题限制:不允许使用外部库。 C++11/C++OX is not allowed. 不允许使用C ++ 11 / C ++ OX。

You naturally have few options: 你自然没有多少选择:

  1. Do not use >> operator and create a function that does the same but accepts three arguments - an input stream, a first object and an input reader object. 不要使用>>运算符并创建一个执行相同但接受三个参数的函数 - 输入流, first对象和输入读取器对象。
  2. Define operator >> that accepts a tuple of first and InputReader as a second argument (ie a pair of pointers). 定义operator >>接受first的元组和InputReader作为第二个参数(即一对指针)。 For example: std::istream& operator>>(std::istream& file, std::pair<first *, InputReader *> & obj) . 例如: std::istream& operator>>(std::istream& file, std::pair<first *, InputReader *> & obj)

You can extend this list indefinitely as long as you have a good imagination. 只要你有很好的想象力,你就可以无限期地扩展这个列表。

Hope it helps. 希望能帮助到你。

UPDATE: 更新:

Here goes some simple example: 这是一个简单的例子:

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

Vlad gives an interesting idea, but I'm not a fan of using std::pair<first, InputReader *> , because that's not the type I want to read. Vlad提出了一个有趣的想法,但我不喜欢使用std::pair<first, InputReader *> ,因为那不是我想读的类型。 I would change your current design slightly. 我会稍微改变你目前的设计。 Move the stream reading functions to a seperate function that takes a stream reference, and also whatever other variables you need, and have the streaming operator call that member. 将流读取函数移动到单独的函数,该函数接受流引用,以及您需要的任何其他变量,并让流操作符调用该成员。 This idea is commonly used when you want operators to have access to optional additional parameters 当您希望操作员可以访问可选的附加参数时,通常会使用此提示

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

And then to implement the reader function, is a direct copy paste, except now you also have error handlers 然后实现读者功能,是直接复制粘贴,除了现在你还有错误处理程序

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

Then, the corresponding change in InputReader's istream function 然后,在InputReader的istream函数中进行相应的更改

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

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

Also, for consistency, replace std::istream& operator>>(std::istream& file, InputReader& obj) with std::istream &InputReader::readFileStream(std::istream& file) . 另外,为了保持一致性,用std::istream &InputReader::readFileStream(std::istream& file)替换std::istream& operator>>(std::istream& file, InputReader& obj) std::istream &InputReader::readFileStream(std::istream& file)

Then in readFileStream you can write if (readObj(file, t)) , and in readObj you can write errorH("oops", -1) . 然后在readFileStream你可以写if (readObj(file, t)) ,而在readObj你可以写errorH("oops", -1)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM