Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

A pointer to a function

Status
Not open for further replies.

firelex

Programmer
Jan 10, 2002
118
DE
Hello, all!
The problem is:
I have two classes:
[tt]MyClass1 and MyClass2[/tt]
The header of [tt]MyClass2[/tt] is included into [tt]MyClass1[/tt], so that [tt]MyClass1[/tt] can create objects of type [tt]MyClass2[/tt].

Now I need to pass a pointer of a member function of [tt]MyClass1[/tt] to [tt]MyClass2[/tt] to let an instance of [tt]MyClass2[/tt] use a function of [tt]MyClass1[/tt].

I did it as follows:
Code:
...
//Somewhere in [tt]MyClass1[/tt]...
MyClass2 obj;
int (*func)(const CString& name);
func = GetTableHeight;
obj.SetExternFunc(func);
...
Code:
...
//In [tt]MyClass2[/tt].....
void MyClass2::SetExternFunc(int (*ext_func)(const CString&))
{
 int abc = ext_func("test");
}
...

It doesn't work. The compiler says:
[tt]
error C2440: '=' : cannot convert 'int (__thiscall MyClass1::*)(const class CString &)' in 'int (__cdecl *)(const class CString &)'
[/tt]

And if I change the variable type :
Code:
...
//Somewhere in [tt]MyClass1[/tt]...
MyClass2 obj;
int ([COLOR=red yellow]MyClass1::[/color]*func)(const CString& name);
func = GetTableHeight;
obj.SetExternFunc(func);
...
this pointer is not valid in MyClass2 context...

Any ideas ????????????????
 
>Any ideas ?

Pass it at reference to the MyClass2 instance instead.

Code:
void MyClass1::DoSomething(const MyClass2& myClass2)
{
 int i =  myClass2.GetTableHeight();
}

If apropriate and MyClass2 exists at least as long as MyClass1 you could let the reference be a member if MyClass1
Code:
class MyClass1
{
	public:
		// Constructor
		MyClass1(MyClass2& myClass2):mMyClass2(myClass) {}

		void DoSomething()
		{
			int i =  mMyClass2.GetTableHeight();
		}
		...
	private:
		MyClass2& mMyClass2;
};

/Per
[sub]
"It was a work of art, flawless, sublime. A triumph equaled only by its monumental failure."[/sub]
 
it is a very good idea, but it is all in MFC and classes are dialog classes.
The point is - I wanted this code work even if the dialogs aren't there and a reference to [tt]this[/tt] is [tt]NULL[/tt]. So the references cannot work
 
>So the references cannot work

Use a pointer instead then.

Code:
void MyClass1::DoSomething(const MyClass2* myClass2)
{
  if (myClass2)
  {
    int i =  myClass2->GetTableHeight();
  }
}

/Per
[sub]
"It was a work of art, flawless, sublime. A triumph equaled only by its monumental failure."[/sub]
 
It's the same in this context - the dialog isn't there, so [tt]this[/tt]-object is [tt]= NULL[/tt]
 
Hi,
You can also use STL to achieve what you want.
The example that follows make use of functors adapted to class member functions. It is closed to your example:
Code:
#include <iostream>
#include <string>

#include <functional>// The interesting header
using namespace std;

//A dummy class
class A
{
public:
  int a_func (const string& s) // the base for the functor
  {
    std::cout << s << std::endl;
    return 0;
  }
};

int main ()
{
  A a;

  mem_fun1_t<int, A, const string&> func1 = mem_fun (&A::a_func);

  return func1 (&a, "hello STL");
}

Hope this helps.

--
Globos
 
>the dialog isn't there, so this-object is = NULL

Since the situation that MyClass2 == NULL is taken care of (the "Use a pointer instead then." post) I assume you mean there is no MyClass1 instance, correct?

Are you executing methods of classes that aren't instantiated? That's bad, unless its a static method - and then 'this' don't even exist.

/Per
[sub]
&quot;It was a work of art, flawless, sublime. A triumph equaled only by its monumental failure.&quot;[/sub]
 
I think I've explained it bad.

Code:
[COLOR=green]//MyClass1.h[/color]
...
#include MyClass2.h
...
Code:
[COLOR=green]//MyClass1.cpp[/color]
...
MyClass2 obj;
int (*func)(const CString& name);
func = GetTableHeight;
obj.SetExternFunc(func);
...
Code:
[COLOR=green]//MyClass2.cpp[/color]
...
void MyClass2::SetExternFunc(int (*ext_func)(const CString&))
{
 int abc = ext_func("test");
}
...

I mean - [tt]MyClass2[/tt] doesn't know anything about [tt]MyClass1[/tt].

Now, where I type it - I understand that it won't go this way... [sad] [sad] [sad]
 
PerFnurt wrote:
Are you executing methods of classes that aren't instantiated? That's bad, ...

Look, if I have a doalog class with a constructor as follows:
Code:
MyClass2::MyClass2(CWnd* pParent /*=NULL*/)
	: CDialog(MyClass2::IDD, pParent)
{
	//{{AFX_DATA_INIT(MyClass2)
	//}}AFX_DATA_INIT
}
and call it -
Code:
MyClass2 dlg;
[tt]MyClass2[/tt] will be instantiated, but as long as I don't call e.g.
Code:
dlg.DoModal();
dialog won't be painted and [tt]this[/tt] will remain [tt]= NULL[/tt]
 
sorry [tt]hWnd[/tt] will remain [tt]= NULL[/tt]

But nevertheless: even if I had a pointer to [tt]MyClass1[/tt] in an instance of [tt]MyClass2[/tt] I couldn't use it - [tt]MyClass2[/tt] needs the header of [tt]MyClass1[/tt] for that. And it would cause a circle including
 
You must use pointer to a member function, not a pointer to an ordinal function. See this snippet, for example:
Code:
class A
{
public:
 void f1(int x) { cout << "A::f1(" << x << ")" << endl; }
 void f2(int x) { cout << "A::f2(" << x << ")" << endl; }
};

typedef void (A::*Afp)(int);

class B
{
  A   a;
  Afp f;
public:
  B():f(0) {}
  void setfun(Afp fp) { f = fp; }
  void doit(int x) 
  { 
    if (f) 
       (a.*f)(x); // sic!
    else 
      cout << "Null ptr" << endl; }
};

int main(int argc, char* argv[])
{
  B  b;
  b.setfun(A::f1); // add & prefix if you wish
  b.doit(123);
  b.setfun(A::f2); // but C++ treats it OK w/o &...
  b.doit(34);
  return 0;
}
It prints:
A::f1(123)
A::f2(45)
See also MSDN (or better some C++ book) about pointers to class members...
 
>MyClass2 needs the header of MyClass1 for that. And it would cause a circle including

Only if you include it in MyClass2's header file, which you dont have to. Put a forward declaration
Code:
class MyClass1;
in the .h and the include in the .cpp

/Per
[sub]
&quot;It was a work of art, flawless, sublime. A triumph equaled only by its monumental failure.&quot;[/sub]
 
>sorry hWnd will remain = NULL

Q: And how is that related to wether references can be used?
A: Not at all.

/Per
[sub]
&quot;It was a work of art, flawless, sublime. A triumph equaled only by its monumental failure.&quot;[/sub]
 
ArkM, what are the benefits of doing such ptr to member function tricks, rather than a 'normal' class (interface) relationship?

/Per
[sub]
&quot;It was a work of art, flawless, sublime. A triumph equaled only by its monumental failure.&quot;[/sub]
 
PerFnurt,
no any special benefits except this is a standard way to deal with pointers to member functions. Let's see 1st post again:
Now I need to pass a pointer of a member function of MyClass1 to MyClass2 to let an instance of MyClass2 use a function of MyClass1.
Well, there is an ordinal sample of that mechanics in my snippet. It works. What else?..
May be I don't understand some details?..
Apropos, I use such pointers not so frequently: too complicated class interface...
 
Ok, thanks.

I intepreted the question slightly different to
'How can I "let an instance of MyClass2 use a function of MyClass1"'

rather than a true need for ptr to member function.

Never used such pointers myself (hence my question).




/Per
[sub]
&quot;It was a work of art, flawless, sublime. A triumph equaled only by its monumental failure.&quot;[/sub]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top