Hi,

I think im trying to break c++ again in making it do something it does not want to do. Basically i have a logging class im making which simply takes a string stream and pumps it into a file. But i want 2 different versions one that trys to force the data to disk and one that doesn't care when it gets written to disk.

To achieve this and save lots of if's i thought id try function pointers. but the thing is i want my function pointer public and the other 2 functions hidden away so the user cannot call them.

how i have tried this below.

/* logger.h */
class Logger
{
public:
	bool SetLogParams(bool diskAtOnce);
	bool CreateLog(const std::string &name, bool overwrite = true);
	void CloseLog(void);
	typedef void (Logger::*FuncPtr)(const std::stringstream &);
	FuncPtr Write;
protected:
	void WriteLogS(const std::stringstream &stream);
	void WriteLog(const std::stringstream &stream);
	std::ofstream log;
};
/* logger.cpp*/
bool Logger::SetLogParams(bool diskAtOnce)
{
	if(diskAtOnce)
	{
		Write = &WriteLogS;
	}
	else
	{
		Write = &WriteLog;
	}
}

void Logger::WriteLog(const std::stringstream &stream)
{
	log<<stream;
}

void Logger::WriteLogS(const std::stringstream &stream)
{
	log<<stream;
	log.flush();
}

As i think you can see i basically want the logger to be able to be set in either mode (at any time but i only intend to use it once at the start) and i call the function pointed to by my function pointer such as

stringstream error;
 error<<"Error occoured: "<<err.no<<err.details<<endl<<endl;
 
 myLog.Write(error);

So that i get the same name to call to write to the log but internally it knows based on my init call which function to use.

The error im geting atm is a compiler one "error C2276: '&' : illegal operation on bound member function expression"

I think this is telling me i cant make public pointer to protected members, so my actual question after all of this is can anyone advise me how to get the interface i want but in the way c++ wants me to do it?


Thanks in advance again!!

Edited 6 Years Ago by Kanoisa: n/a

Your statement

Write = &WriteLogS;

should be

Write = &Logger::WriteLogS;

and similarly for the other similar statement.

Your problem is that a function pointer is essentially a C feature and does not support methods (that is a function acting on an object). So you can only make function pointers to static class methods or global (or namespaced) functions.

>>As i think you can see i basically want the logger to be able to be set in either mode (at any time but i only intend to use it once at the start)
Why not use polymorphism? Try something like this:

/* logger.h */
class Logger
{
  public:
    bool CreateLog(const std::string &name, bool overwrite = true);
    void Write(const std::stringstream& stream);
    void CloseLog(void);
    virtual ~Logger() { };
  protected:
    virtual void WriteLog(const std::stringstream &stream) = 0;
    std::ofstream log;
};

class SyncLogger : public Logger {
  protected:
    void WriteLog(const std::stringstream& stream);
};
class AsyncLogger : public Logger {
  protected:
    void WriteLog(const std::stringstream& stream);
};
/* logger.cpp*/
void Logger::Write(const std::stringstream &stream)
{
	WriteLog(stream);
}

void AsyncLogger::WriteLog(const std::stringstream &stream)
{
	log<<stream;
}

void SyncLogger::WriteLog(const std::stringstream &stream)
{
	log<<stream;
	log.flush();
}

Then at the start, you create either a SyncLogger or a AsyncLogger depending on the case.

There are many other solutions also, that I'm sure will come up on this thread. But function pointers is really not a particularly good one (I would say the worst.. function pointers are deprecated in C++ as far as I'm concerned).

Edited 6 Years Ago by mike_2000_17: n/a

Ahh i see, as the next issue i came up with was that the compiler was silent but it didnt work:P, Mike im going to try your solution. I never tried polymorphism before never understood it but this makes sence: its like having 2 classes derived from logger that impliment the virtual functuions(one in this case) differently?

Edited 6 Years Ago by Kanoisa: n/a

Ahh i see, as the next issue i came up with was that the compiler was silent but it didnt work:P

What do you mean "it didn't work"? In the code you posted, you never actually use your Write member, so what didn't your code do that you expected it would do?

>>its like having 2 classes derived from logger that implement the virtual functions(one in this case) differently?

Exactly.

In this case it is very trivial because it's only one line of code different. You could just as well have a bool data member in your class Logger and it would work fine too:

/* logger.h */
class Logger
{
  public:
    bool CreateLog(const std::string &name, bool overwrite = true);
    void Write(const std::stringstream& stream);
    void CloseLog(void);
    Logger(bool aIsSync = true) : log(), IsSync(aIsSync) { };
    virtual ~Logger() { };
  protected:
    std::ofstream log;
    bool IsSync;
};

/* logger.cpp*/
void Logger::Write(const std::stringstream &stream)
{
	log<<stream;
        if(IsSync)
	  log.flush();
}

it was telling me that Write did not equate to a function taking 1 arguments, i tried a few things and i coulden't get it.

Thanks for your help both of you its appreciated and using the polymorphism it now works.

Thanks again to you both job done :)

This question has already been answered. Start a new discussion instead.