Link to home
Start Free TrialLog in
Avatar of F-J-K
F-J-KFlag for Canada

asked on

How Can I Pass Function as an Argument? C/C++

Every time i pass an address of a function to a pointer, i get error says:

error C2102: '&' requires l-value

1. How can i fix it?
2. Why can't we just do void *app(void), instead of void (*app)(void)?
exitApplication(void (*app)(void))
{
        //point to the sepcified function
       app();
}
 
//***********************************************//
exitApplication(&mainMenu());

Open in new window

Avatar of Kent Olsen
Kent Olsen
Flag of United States of America image

It's a small syntax issue.  :)

  exitApplication(&mainMenu());

That tries to run the function mainMenu and return the address of "something".  Probably not what you want to do.

  exitApplication(mainMenu);

That passes the address of mainMenu to exitApplication.  That's probably what you want to do.

Note that if mainMenu is a class method, it can get somewhat more complicated.


Good Luck,
Kent
Avatar of fmmexpertexchange
fmmexpertexchange

Change "exitApplication(&mainMenu());" by "exitApplication(mainMenu);"
Avatar of F-J-K

ASKER

I did it, i got this error:

error C3867: 'MenusLayout::mainMenu': function call missing argument list; use '&MenusLayout::mainMenu' to create a pointer to member

mainMenu resides in MenusLayout class anyway, so why should i do call the class as MenusLayout::?

Here is the code as you see it below...

This a simple command line remote administration tool for my project.

Everytime user want to exit, he/she will be asked for confirmation. If he/she presses no, user should in the same page. The only to do it, is to call the same page (function) that user is curently in.
#include <sstream>
#include "MenusLayout.h"
#include "ConsoleDesign.h"
 
const int EXIT = -1;
ConsoleDesign windowDes;
 
MenusLayout::MenusLayout()
{
	//empty constructor
}
 
MenusLayout::~MenusLayout()
{
	//empty destructor
}
 
 
void MenusLayout::mainMenu()
{
	do
	{
		choice_is_invalid = false;
 
		windowDes.coloringText(3);
		cout<<"\nEnter a choice: ";
		windowDes.coloringText(7);
 
		int receiveUserInput = getUserChoice<int>();
 
		switch(receiveUserInput)
		{
			case 1:
				//.......
				break;
			case 2:
				//.......
				break;
			case 3:
				//.......
				break;
			case EXIT:
                                     //*********HERE
				exitApplication(mainMenu);
				break;
			default:
				windowDes.coloringText(6);
				cout<<"Choice is invalid."<<endl;
				choice_is_invalid = true;
				break;
		}
	}while(choice_is_invalid);
 
}
 
void MenusLayout::buildRemoteController()
{
	do
	{
		choice_is_invalid = false;
 
		windowDes.coloringText(3);
		cout<<"\nEnter a choice: ";
		windowDes.coloringText(7);
 
		int receiveUserInput = getUserChoice<int>();
 
		switch(receiveUserInput)
		{
			case 1:
				//.......
				break;
			case 2:
				//.......
				break;
			case 3:
				system("cls");
				windowDes.headerDesign();
				mainMenuDisplay();
				mainMenu();
				break;
			case EXIT:
                                     //******HERE
				exitApplication(buildServer); 				break;
			default:
				windowDes.coloringText(6);
				cout<<"Choice is invalid."<<endl;
				choice_is_invalid = true;
				break;
		}
	}while(choice_is_invalid);
 
}
 
 
//*************HERE
void MenusLayout::exitApplication(void (*app)(void))
{
	do
	{
		choice_is_invalid = false;
 
		windowDes.coloringText(12);
		cout<<"\nAre you sure you want to exit - Y/N? ";
 
		char exitConfirmation = getUserChoice<char>();
 
		switch(exitConfirmation)
		{
			case 'y':
				exit(0);
				break;
			case 'Y':
				exit(0);
				break;
			case 'n':
				app();
				break;
			case 'N':
				app();
				break;
			default:
				windowDes.coloringText(6);
				cout<<"Choice is invalid - Please enter Y or N"<<endl;
				choice_is_invalid = true;
				break;
		}
	}while(choice_is_invalid);
}

Open in new window

SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
There's a difference between a function pointer, and a member function pointer.

So :
void MenusLayout::exitApplication(void (MenusLayout::*app)(void)) {
    (*this.*app)();
}
 
MenusLayout ml;
ml.exitApplication(&MenusLayout::mainMenu);

Open in new window

Avatar of F-J-K

ASKER

Thanks jkr & Infinity08. My code worked. Since this is first time implementing  such a code, i have some questions...

Thats how i understand it:

void MenusLayout::exitApplication(void (MenusLayout::*app)(void))

this means the parameter will point to a function. Thus, the passed argument be be preceded with & (to pass the address).

When user passes the address of the function, this will be executed (this->*app)();

1. (this->*app)(); means the function resides in the scope (MenusLayout) and will be pointing to where function resides - Can you explain this part please i do not understand it fully.

2. exitApplication(&MenusLayout::mainMenu);

Function address is passed. Why we have to use MenusLayout? mainMenu resides inside MenusLayout. I think because MenusLayout has its own address, while its member function have their own addresses. Right?

3. But, why this wouldn't work exitApplication(&mainMenu);? Pointer eventually will point to the target function we not need to go through MenusLayout address first. Can you explain please?

4. Assume, we have MenusLayout::mainMenu() { //implementation}
MenusLayout::designApplication() { //implementation}

Usually if i want to call mainMenu in designApplication, i just call it normally as:

MenusLayout::designApplication() { mainMenu(); } ....

Why it does not force me to call it as MenusLayout::designApplication() { MenusLayout::mainMenu(); }?

Avatar of F-J-K

ASKER

Thanks for being patience
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of F-J-K

ASKER

Can i call you a life saver?