JefPatat

Hi all,

you guys helped me out before, I hope you can with this thing I'm trying, actually it is working but I would like to do it in another cleaner/better way for learning purposes. I work within the limitations of a framework which is written by other people and for several reasons I did some 'hacking' to achieve better results.

I have a window class (a bit like a form) in which I have several buttons classes of my own. The reason for not using the framework buttons is that their navigation order (comparable to tab order in windows navigation) behaves like an invention of the devil himself. The consequence is that I have to do the navigation myself. So I know when a button will be pushed because my code "pushes" it.

To do all this I made several inherited button classes each having it's own OnDown function in which a function of the only instance of the window class is called.

So there are several things I do not like:
- if I were to create several instances of the window this would mean I have to double the number of inherited button classes
- why do I need to inherit the button classes if the only thing that differs is the OnDown function

I am trying to solve this by first passing a pointer to the function that needs to be executed in the window class to the button class. And I'm trying to do this IN the window class. That way I can change what the button needs to execute before my code "pushes" it.

If I would succeed in this I think I overcome both my problems. Of course, as you can guess, I do not succeed because I do not fully master the concept nor the syntax. I have tried all combinations I can think of and always the compiler was complaining.

Help is appreciated!

Here is my idea in codeform:

Code Snippet

CButton::CButton(...) : CButtonParent(...)
{
...
functionPointer
...
}

CButton::SetOnDownFunction(pointer)
{
this->functionPointer = pointer
}

CButton::Push()
{
...
executer fuction from functionPointer
...
}

CWindow::CWindow(...) : CParentWindow(...)
{
firstButton = new CButton();
firstButton->SetOnDownFunction(pointer to OnFirstButtonDown);
secondButton = new CButton();
secondButton ->SetOnDownFunction(pointer to OnSecondButtonDown);
thirdButton = new CButton();
thirdButton->SetOnDownFunction(pointer to OnThirdButtonDown);
}

CWindow::OnFirstButtonDown(){...}
CWindow::OnSecondButtonDown(){...}
CWindow::OnThirdButtonDown(){...}

CWindow::OnNavigate()
{
...
firstButton->Push();
...
secondButton->Push();
...
thirdButton->Push();
...
}



Re: Visual C++ General Member function pointers

Simple Samples

I apologize if I don't understand, but since you are trying to use a function pointer, perhaps an easier soluton is to use a virtual function. You will still need to derive classes for each variation but everything else will be easy.

I do not understand the problem with navigation and why you are calling the Push function, but it is nearly certain you can use a more direct solution. Or perhaps you can simplify the solution by using navigation the way it was intended to be used; perhaps it is simply a matter of understanding it.






Re: Visual C++ General Member function pointers

_johnr_

Hi Jef,

The better way you're looking for is a delegate. Alas, not built in to C++ by default. There are plenty of third party libraries that will give you this functionality for free. If you're not taking Sam's advice with regards to using the functionality already present in the library I would advise you to look into that.

If you insist on using member pointers you can do something like this:

Code Snippet

typedef void (CWindow::*PushCallback)(void);

class CButton : public CButtonParent

{

PushCallback _PushCallback;

void SetOnDownPointer(PushCallback pushCallback)

{

_PushCallback = pushCallback;

}

void Push(void)

{

if(_PushCallback)

(PointerToCWindowsInstance->*_PushCallback)();

}

};

class CWindow : public CWindowParent

{

CWindow()

{

firstButton = new CButton();
firstButton->SetOnDownFunction(&CWindow::OnFirstButtonDown);

}

};

You could probably also pass the instance of CWindow to call, to your SetOnDownPointer function.

John.





Re: Visual C++ General Member function pointers

crescens2k

johnr's idea is fairly close to a good one.

When you override the button you add a new member function and member variable.

void CMyButton:Tongue TiedetPointer(MYPTR* mPtr);

MYPTR* CMyButton::myptr;

The MYPTR is a function pointer to the function you want called.

typedef void (MYPTR*)(/*Params*/);

(I apologise if the above typedef is not correct since I don't have access to all my references right now)

Once you have this then you set myptr with the SetPointer method and then you override the OnButtonDown method calling the myptr function pointer.

myptr(/*params*/);

Maybe a look into pointer to members too would be a good idea.

johnr:

It is true that native C++ doesn't have delegates but they have function pointers so the basic ideas can still work. Delegates are really type checked functio pointers anyway.






Re: Visual C++ General Member function pointers

_johnr_

It is true that native C++ doesn't have delegates but they have function pointers so the basic ideas can still work. Delegates are really type checked functio pointers anyway.

Absolutely, but the downside of pointers to member functions is that the class that uses the pointer has to know about the type its calling, that, of course, totally sucks and makes it impossible to write reusable code.

Never having written a C++ compiler I can say this with absolute confidence; if they ever standardised C++ delegates it would be the easiest feature they ever had to add to a compiler. Stick out tongue

John.





Re: Visual C++ General Member function pointers

Simple Samples

I still don't understand the need to call a function that processes a message. It is possible that it is a good design, but I suspect the design can be simplified. The original question begins by explaining that navigation (tab order) is not working correctly.




Re: Visual C++ General Member function pointers

crescens2k

I'll try to explain how I see it.

Hi all,

you guys helped me out before, I hope you can with this thing I'm trying, actually it is working but I would like to do it in another cleaner/better way for learning purposes. I work within the limitations of a framework which is written by other people and for several reasons I did some 'hacking' to achieve better results.

I have a window class (a bit like a form) in which I have several buttons classes of my own. The reason for not using the framework buttons is that their navigation order (comparable to tab order in windows navigation) behaves like an invention of the devil himself. The consequence is that I have to do the navigation myself. So I know when a button will be pushed because my code "pushes" it.

To do all this I made several inherited button classes each having it's own OnDown function in which a function of the only instance of the window class is called.

So there are several things I do not like:
- if I were to create several instances of the window this would mean I have to double the number of inherited button classes
- why do I need to inherit the button classes if the only thing that differs is the OnDown function

The reasoning for doing all this. What he has is several classes which differ only in one function and instead of creating this class just differing by one function, he wants a general button which he can change the functionality before he clicks it. This is to overcome the limitations of what he is using.

I am trying to solve this by first passing a pointer to the function that needs to be executed in the window class to the button class. And I'm trying to do this IN the window class. That way I can change what the button needs to execute before my code "pushes" it.

If I would succeed in this I think I overcome both my problems. Of course, as you can guess, I do not succeed because I do not fully master the concept nor the syntax. I have tried all combinations I can think of and always the compiler was complaining.

Help is appreciated!

He originally had an idea about using a function pointer to do all the work for him, in this case I think that it is the most effective idea. Set the pointer and then click, the function itself can be set but the important thing here is how to do it. So I gave the simplest idea on how to do it that I could think of.

I can't think of anything simpler apart for doing the one thing this person doesn't want. In all of my experience in using C/C++ there is only one simple method for modifying behaviour on the fly like this.

Well, as I said, that is how I see it. I also don't like to say to somebody "no don't do it like that, do it like this." I learned quite a few things with just trying out ideas so I don't like to stop people finding out whether they can pull something off. Of course, on our end it is not easy to give our opinions either when they don't give all possible information, like is doing this needed for example, but at the same time class libraries like the MFC work by using similar ideas.






Re: Visual C++ General Member function pointers

JefPatat

Thanks John,

I remember yesterday I had a similar solution but I do know that I always had :

Code Snippet
firstButton->SetOnDownFunction(&CWindow::OnFirstButtonDown());

instead of

Code Snippet

firstButton->SetOnDownFunction(&CWindow::OnFirstButtonDown);

which did not work because of syntax.

I got it to work thanks to your sample, I had to search a bit because of the cyclic inclusion but i managed to solve that with the class CWindos; line

Code Snippet

typedef void (CWindow::*PushCallback)(void);

class CButton : public CButtonParent

{

class CWindow;//to avoid cyclic inclusion

PushCallback _PushCallback;

CWindow * parentWindow;

void SetOnDownPointer(PushCallback pushCallback, CWindow * parentWindow)

{

_PushCallback = pushCallback;

this->parentWindow = parentWindow;

}

void Push(void)

{

if(_PushCallback)

(parentWindow->*_PushCallback)();

}

};

class CWindow : public CWindowParent

{

CWindow()

{

firstButton = new CButton();
firstButton->SetOnDownFunction(&CWindow::OnFirstButtonDown);

}

};

crescens2k can you please clarify, I don't understand your sample nor do I see why it is better.

Thanks so far!