TheBeardless
TheBeardless

Reputation: 67

Is it possible to call a function without a direct reference in C++?

beginner here

I am trying to make a "logger" for my c++ learning project, I´ve already set up code to manage the logging itself, but I can´t get the function to work from other classes.

Here´s my "Debugger" class

class MSEdebug
    {

        MSEdebug(){logOutput.open("log.txt");}

        ~MSEdebug() { logOutput.close(); }

        void debuglog(std::string info)
        {
#ifdef DEBUG
            std::cout << "LOG:" << info << std::endl;
#endif // DEBUG
            logOutput << "LOG:" << info << "\n";
        }

        std::ofstream logOutput;


    };

And here´s what I want to be able to do:

#include "MSE_debug.h"

//...

MSEapp::debugTest()
{

     MSEdebug::debuglog("Test, 1, 2, 3...");

}

Now this doesn´t work, and you experienced C++ programmers are probably rolling your eyes already, but could you be so kind to tell me how I would get it to work.

Btw, I hope I´ve done this correctly, this is my first question, so I´m sorry if it´s bad

Upvotes: 3

Views: 152

Answers (3)

Serge Ballesta
Serge Ballesta

Reputation: 149125

The canonical way is to use the singleton pattern to have a unique instance of the class MSEDebug that is easily accessible.

class MSEdebug
    {

        MSEdebug(){logOutput.open("log.txt");}
    public:
        ~MSEdebug() { logOutput.close(); }

        void debuglog(std::string info)
        {
#ifdef DEBUG
            std::cout << "LOG:" << info << std::endl;
#endif // DEBUG
            logOutput << "LOG:" << info << "\n";
        }
        static MSEdebug& getInstance() {
            static MSEdebug instance;

            return instance;
        }
    private:
        std::ofstream logOutput;
    };

You can then use it that way:

     MSEdebug::getInstance().debuglog("Test, 1, 2, 3...");

Upvotes: 3

ravenspoint
ravenspoint

Reputation: 20586

Yes. You need to use a static function. Here is some code to get you started.

class MSEdebug
    {
public:
        MSEdebug(){}

        ~MSEdebug() { logOutput.close(); }

        static void debuglog(std::string info)
        {
#ifdef DEBUG
            std::cout << "LOG:" << info << std::endl;
#endif // DEBUG
            if( ! logOutput.is_open() )
            { 
               //first use - open logfile
               logOutput.open("log.txt");
            }
            logOutput << "LOG:" << info << "\n";
        }

        static std::ofstream logOutput;


    };

You will have to construct logOutput somewhere in a .cpp file

std::ofstream MSEdebug::logOutput;

BTW someone suggested "you need an actual variable of type MSEdebug". This is wrong. If you do it that way, each time you construct an "actual variable" the class will try to open another copy of the log file.

Upvotes: -1

quamrana
quamrana

Reputation: 39404

This might be the one case where a singleton might be in order:

class MSEdebug {
private:
    MSEdebug(){ logOutput.open("log.txt"); }

    ~MSEdebug() { logOutput.close(); }
public:
    static MSEdebug& instance(){
        static MSEdebug debug;
        return debug;
    }
    void debuglog(std::string info) {
#ifdef DEBUG
        std::cout << "LOG:" << info << '\n';
#endif // DEBUG
        logOutput << "LOG:" << info << '\n';
        }
private:
    std::ofstream logOutput;
};

Usage like this:

#include "MSE_debug.h"

//...

MSEapp::debugTest()
{
     MSEdebug::instance().debuglog("Test, 1, 2, 3...");
}

Upvotes: 4

Related Questions