access from static function to non-static function

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
greg
Earned some good credits
Earned some good credits
Posts: 111
Joined: Fri Sep 12, 2008 7:17 am

access from static function to non-static function

Post by greg »

I have the following problem.
Here is my piece of code:

Code: Select all

class MyPanel : public wxPanel
{
public:
    MyPanel(MyFrame *frame);
    virtual ~MyPanel();

private:
	void start_database ();

protected:
	static int getStartPoint(DPoint3d * pt,int view);
};

/*----------------------------------------------------------------------+
name          start_database					             +----------------------------------------------------------------------*/
void MyPanel::start_database ()
	{

	printf ("start_database\n");
	return;
}
/*----------------------------------------------------------------------+
name		getStartPoint						+----------------------------------------------------------------------*/
int MyPanel::getStartPoint (Dpoint3d *pt, int view)
	{
	start_database ();

	return TRUE;
	}
/*----------------------------------------------------------------------+
|	OnStartClick	                                       				|
+----------------------------------------------------------------------*/
void MyPanelBaza::OnStartClick( wxCommandEvent& WXUNUSED(event) )
{
	mdlState_startPrimitive (getStartPoint, NULL, 0, 0);

}
While compiling my code I got the following error:
error C2352: 'MyPanel::start_database' : illegal call of non-static member function
see declaration of 'start_database'


So How can I access from static getStartPoint function to non-static function start_database.

Can anybody help me and correct my code to compile?
Regards
Greg
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2409
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Post by evstevemd »

static functio does not belong to object of the class so you cannot access it like that! Call the function like below:

Code: Select all

MyPanel::start_database ()
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
briceandre
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 672
Joined: Tue Aug 31, 2010 6:22 am
Location: Belgium

Post by briceandre »

static functio does not belong to object of the class so you cannot access it like that! Call the function like below:
The problem is just the oposite : getStartPoint s a static function. So, it has no reference to an object of class MyPanel. So, it cannot call a non-static function, as it has no idea of the object on which it shall invoke this method.

If you want to keep same design, you should provide a pointer to the object to static function :

Code: Select all

static int getStartPoint(DPoint3d * pt,int view, MyPanel* obj)
{
    obj->start_database ();

    return TRUE;
}
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2409
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Post by evstevemd »

why not make a database class a singleton? In that way you will save a lot of pains!
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
greg
Earned some good credits
Earned some good credits
Posts: 111
Joined: Fri Sep 12, 2008 7:17 am

Post by greg »

evstevemd
I haven't use singleton at all.
Can You implement singleton on my sample?
Regards
Greg
briceandre
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 672
Joined: Tue Aug 31, 2010 6:22 am
Location: Belgium

Post by briceandre »

A singleton is a class that can be instanciated only once. But, here, the question is : is a singleton a good idea ? Or, in other words, are you sure you only manage to instanciate once your MyPanel class ?

If you really want, you can do something like this (but I don't thinks it's a good idea in your case...)

Code: Select all

class MyPanel : public wxPanel
{
private:
    MyPanel(MyFrame *frame);
public:
    MyPanel& GetSingleton(MyFrame *frame)
    {
       static MyPanel* panel = new MyPanel(frame);
       return *panel;
    }
    virtual ~MyPanel();

private:
        void start_database ();

protected:
        static int getStartPoint(DPoint3d * pt,int view);
};
You can thus replace your static function with :

Code: Select all

int MyPanel::getStartPoint (Dpoint3d *pt, int view)
        {
        GetSingleton(NULL).start_database ();

        return TRUE;
        }
The fact that you invoke GetSingleton with NULL is not a problem because, if it has already been called once with correct parameters, the NULL parameter will not be taken into account anymore. But, the important point is that, if you try to re-use this panel in a new frame, your app will crash...
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2409
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Post by evstevemd »

I will write one but if you use CodeLite IDE then there is a way of creating new class and tell it to meke it a singleton. I use mobile now but later I will do that for you. just give me class name
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2409
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Post by evstevemd »

Header file

Code: Select all

class NotesEditor : public wxPanel {

	static NotesEditor* ms_instance;

public:
	static NotesEditor* Instance(wxWindow* parent=NULL);
	static void Release();

private:
	NotesEditor(wxWindow* parent);
	~NotesEditor();
	//----------
}
CPP File

Code: Select all

NotesEditor* NotesEditor::ms_instance = 0;

NotesEditor::NotesEditor(wxWindow* parent): wxPanel(parent) {
	//-----------------------------
}

NotesEditor::~NotesEditor() {
}

NotesEditor* NotesEditor::Instance(wxWindow* parent) {
	if(ms_instance == 0) {
		ms_instance = new NotesEditor(parent);
	}
	return ms_instance;
}

void NotesEditor::Release() {
	if(ms_instance) {
		delete ms_instance;
	}
	ms_instance = 0;
}
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
briceandre
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 672
Joined: Tue Aug 31, 2010 6:22 am
Location: Belgium

Post by briceandre »

You should not use the Release function because a wxWindow is deleted by its father. This is the reason why I proposed a code that did not allow deleting the allocated object.

Appart that point, my code is equivalent to yours (and a bit simplier, I think :-) ). But I still think it's not a good idea to make a singleton in that case. You do not make a singleton only because you have to provide a pointer to the object in a callback. If your need is that, you provide the pointer to the callback, that's all...
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2409
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Post by evstevemd »

briceandre wrote:You should not use the Release function because a wxWindow is deleted by its father. This is the reason why I proposed a code that did not allow deleting the allocated object.

Appart that point, my code is equivalent to yours (and a bit simplier, I think :-) ). But I still think it's not a good idea to make a singleton in that case. You do not make a singleton only because you have to provide a pointer to the object in a callback. If your need is that, you provide the pointer to the callback, that's all...
I always Call Release in wxApp Exit function. In case things were not as planned :wink:

I have used the code for long now and I will check yours and adapt, you know i love simplicity :roll:
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2409
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Post by evstevemd »

[quote="briceandre"But, here, the question is : is a singleton a good idea ? Or, in other words, are you sure you only manage to instanciate once your MyPanel class ?[/quote]
brice,
I think OP wants database thing to happen once (eg reusing connections et al). But he/she have to separate DB functions from GUI stuff and put them in singleton. If that is the case he could add another method like Reconnect(some credentials) to change connection to different database.

Let us here the OP himself on what he wants :D
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
briceandre
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 672
Joined: Tue Aug 31, 2010 6:22 am
Location: Belgium

Post by briceandre »

But he/she have to separate DB functions from GUI stuff and put them in singleton.
I agree, but in the code you proposed, the part you are putting in a singleton IS the GUI stuff (wxPanel), and not the DB stuff !! And this point is a bad idea, for me...

The proof ? In the small sample you provided, there was already a potential big mistake with the deletion of a wxWindow. And I must admit that I nearly made the same mistake when I wrote the small piece of code I previously posted on this subject....

But, I agree on the fact that greg can choose whatever design he wants :-)
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2409
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Post by evstevemd »

briceandre wrote: I agree, but in the code you proposed, the part you are putting in a singleton IS the GUI stuff (wxPanel), and not the DB stuff !! And this point is a bad idea, for me...
Yeah because I have to share same instance in Many Places you know. The only way is that. May be I'm poor at design, may be not :shock:
briceandre wrote:The proof ? In the small sample you provided, there was already a potential big mistake with the deletion of a wxWindow. And I must admit that I nearly made the same mistake when I wrote the small piece of code I previously posted on this subject....
I will review my code but it works :oops:
briceandre wrote:But, I agree on the fact that greg can choose whatever design he wants :-)
Sure :P
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
Auria
Site Admin
Site Admin
Posts: 6695
Joined: Thu Sep 28, 2006 12:23 am
Contact:

Post by Auria »

Check http://wiki.wxwidgets.org/Sharing_info_between_dialogs as a starting point. There are more advanced design techniques but seems like you need to start from the vewry beginning ;)
"Keyboard not detected. Press F1 to continue"
-- Windows
briceandre
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 672
Joined: Tue Aug 31, 2010 6:22 am
Location: Belgium

Post by briceandre »

Yeah because I have to share same instance in Many Places you know.
But you cannot share the same instance of a gui element between several places. That is the problem, and that is why a singleton does not seem to be a good candidate to solve the problem.
I will review my code but it works
If you share the instance of your NotesEditor between several frames or if you invoke your Release function, it will crash. That's just a question of time (and luck). You cannot delete an wxWindow that is owned (directly or indirectly) by a frame or a dialog. And you cannot share a wxWindow between several parents.

In conclusion, I would follow Auria advice and find another way to transmit the pointer of the wxPanel than to declare it as a singleton.

Just a question, Greg, do you have te possibility to change the callback mechanism ? A good practice when writing callback mechanism is to let a spare argument to the callback, generally called 'user_data' and of type 'void*' for which the user can register whatever he wants when registering it's callback and that the callback will receive when it will be invoked. With such a design, all you have to do is to provide the pointer to your object as 'user_data' and your problem is solved. But I don't know what is allowed by your function mdlState_startPrimitive...
Post Reply