Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a method as a variable in C++

I'm working on an irc bot as a way to help me learn c++ and I was wondering if it is possible to use a method as a variable like this:

//Irc.h
public:

void *onJoin(char* sender, char* channel);
/////

//Main.cpp
void join(char* sender, char* channel)
{
    cout << sender << endl;
    cout << channel << endl;
}
int main()
{
    Irc irc(stuff);
    irc.onJoin = join;
}
like image 277
Jesse Laning Avatar asked Dec 11 '22 14:12

Jesse Laning


2 Answers

Yes, it is possible. These variables are called functions pointers. The can write it like this:

void onJoin( char* sender, char * channel );

int main(void)
{
    void (*func)(char *,char *);
    func = &onJoin;
    func( "sender", "channel" );
}

Alternatively you can use std::function<> for that. The code would be the same except for the first line in main() which is replaced by

    std::function<void(char*,char*)> func;

This is a bit more legible in my opinion. If you use this, then don't forget to add

#include <functional>

to the top of your file. Instead of using such variables in a function, you can also use them as member variables of any struct or class.

like image 78
Ralph Tandetzky Avatar answered Dec 14 '22 04:12

Ralph Tandetzky


You need a pointer-to-function:

void* (*OnJoinFn)(char*, char*);

In your Irc class,

class Irc
{
public:
  OnJoinFn onJoin;
};

This can be assigned as you are doing above:

int main()
{
    Irc irc(stuff);
    irc.onJoin = join;
}

But I wonder, if you are just learning C++, do you really need a pointer-to-function? pointers-to-function are certianly legal and valid, but an unusual entity and I would typically expect to use some other mechanism. As a start, I would suggest looking in to abstract base classes:

class IIrc
{
public:
  virtual void* OnJoin(const char*, const char*) = 0;  // pure virtual
  virtual ~IIrc() {}; // Don't forget to implement a virtual destructor in any ABC
};

class MyIrc 
:
  public IIrc
{
public:
  void* OnJoin(const char* sender, const char* channel*)
  {
    // YOUR CODE HERE
  }
};

int main()
{
  IIrc* irc = new MyIrc;
  irc->OnJoin (...);
}

I've taken the liberty of introducing const correctness in OnJoin.

You should also consider not returning a void*, which bypasses most of C++'s type safety mechanisms, but a pointer to an actual object, or another interface.

Finally, using new (and delete, which is missing here, resulting in a memory leak) is poor practice. Instead, prefer to allocate things on the stack or, if you really need dynamic allocation, use a smart pointer.

like image 22
John Dibling Avatar answered Dec 14 '22 03:12

John Dibling