[英]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. 唯一的问题是,在
first
读errorH
我无法访问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: 你自然没有多少选择:
>>
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
对象和输入读取器对象。 >>
that accepts a tuple of first
and InputReader
as a second argument (ie a pair of pointers). >>
接受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.