LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-04-2011, 11:05 PM   #1
Aquarius_Girl
Senior Member
 
Registered: Dec 2008
Posts: 4,731
Blog Entries: 29

Rep: Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940
C++: callbacks


I am unable to understand the highlighted code/syntax here
and what do variable names starting with an underscore represent?
Code:
#include <iostream>

template <class Class, typename ReturnType, typename Parameter>
class SingularCallBack
{
public:
  typedef ReturnType (Class :: *Method)(Parameter);
  
  SingularCallBack (Class *_class_instance, Method _method)
  {
    class_instance = _class_instance;
    method         = _method;
  };
  
  ReturnType execute (Parameter parameter)
  {
    return (class_instance->*method)(parameter);
  };

private:  
  Class  *class_instance;
  Method method;
};

class A
{
public:  
  void output()
  {
    std :: cout << "I am class A :D\n";
  };
};

class B
{
public:  
  bool methodB (A a)
  {
    a.output();
    return true;
  }
};

int main ()
{
  A a;
  B b;
 
  SingularCallBack <B, bool, A> *cb;
  cb = new SingularCallBack <B, bool, A> (&b, &B :: methodB);

  if (cb->execute (a))
    {
      std::cout << "CallBack Fired Successfully!" << std::endl;
    }
  else
    {
      std::cout << "CallBack Fired Unsuccessfully!" << std::endl;
    }

  return 0;
}

Last edited by Aquarius_Girl; 03-05-2011 at 01:13 AM.
 
Click here to see the post LQ members have rated as the most helpful post in this thread.
Old 03-05-2011, 02:31 AM   #2
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,515

Rep: Reputation: 239Reputation: 239Reputation: 239
does this help?

http://www.parashift.com/c++-faq-lit....html#faq-33.1

cplusplus.com is good too.

variables/functions with starting underscores are a convention in libraries and implementations to
prevent namespace clashes, look in some header files.
typically they denote internal stuff.
In this case the coder is differentiating the parameter from the
data member.

by convention in userland one should not use them.
if you do, people will dissapprove, though it's only convention.
in short they have no meaning to C++, only humans

Last edited by bigearsbilly; 03-05-2011 at 03:03 AM.
 
2 members found this post helpful.
Old 03-05-2011, 03:25 AM   #3
Aquarius_Girl
Senior Member
 
Registered: Dec 2008
Posts: 4,731

Original Poster
Blog Entries: 29

Rep: Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940
Billy,

That was very helpful, thanks for taking your time.
 
Old 03-05-2011, 03:30 AM   #4
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,515

Rep: Reputation: 239Reputation: 239Reputation: 239
also, I'm a bit rusty but, generally
initialisation lists are preferred over assignment in constructors:
Code:
 SingularCallBack (Class  * const _class_instance, Method _method):
  class_instance(class_instance),
  method(_method)
  {
    //class_instance = _class_instance;
    //method         = _method;
  }
http://www.parashift.com/c++-faq-lit....html#faq-10.6
 
1 members found this post helpful.
Old 03-05-2011, 05:09 AM   #5
Aquarius_Girl
Senior Member
 
Registered: Dec 2008
Posts: 4,731

Original Poster
Blog Entries: 29

Rep: Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940
Again a helpful pointer, thanks Billy for being around and that site is worth bookmarking!

Last edited by Aquarius_Girl; 03-05-2011 at 05:42 AM.
 
Old 03-05-2011, 05:13 AM   #6
Aquarius_Girl
Senior Member
 
Registered: Dec 2008
Posts: 4,731

Original Poster
Blog Entries: 29

Rep: Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940
In the below code, the highlighted syntax means that functionName is a function of a class and method is the "object" of the function, functionName??? Please clarify.
Code:
template <class dummyClass, typename ReturnType, typename Parameter>
class SingularCallBack
{
public:
  typedef ReturnType (dummyClass :: *functionName)(Parameter);
  
  SingularCallBack (dummyClass *_class_instance, functionName _method)
  {
    class_instance = _class_instance;
    method         = _method;
  };
  
  ReturnType execute (Parameter parameter)
  {
    return (class_instance->*method)(parameter);
  };

private:  
  dummyClass  *class_instance;
  functionName method;
};
 
Old 03-05-2011, 06:04 AM   #7
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
In that typedef, functionName is the type being defined.

ReturnType, dummyClass, and Parameter are all types used to define functionName.

If you don't yet understand the way "pointer to member functions" work in C++, you should read some tutorial on that topic. I did a quick google search, and at first glance, the best looking tutorial I saw was
http://www.goingware.com/tips/member-pointers.html
But I haven't reviewed it carefully, so it might not be as good as it looked at first glance. If you don't like that one, redo the google search and try another.

For your example, you also would need to understand the basics of templated class definition. But you probably already understand that, and even if you didn't you should learn the "pointer to member function" syntax and meaning first in order to understand your example.

Edit: I just noticed your other thread on this same topic seems to imply more understanding of "pointer to member" and less understanding of templating. So I don't have a good estimate of what you know vs. what you want explained.
http://www.linuxquestions.org/questi...3/#post4279696

In that thread, you asked how to avoid the typedef. I think that is a foolish thing to even want to do. The code would be far uglier and less readable without the typedef.

But if you really wanted to dump the typedef, you could do that in the same way one would dump any typedef. Use the full (ugly) type specification in each place that the code now uses the typedef.

Regarding your templating confusion in the other thread:
Code:
template <class MyDummyClass, typename  (MyDummyClass ::*Method)(Parameter), typename Parameter>
I don't think anything like that is possible in C++. You must put simple names for deduced types in that list and then represent their association into compound types within the body of the definition.

Last edited by johnsfine; 03-05-2011 at 06:23 AM.
 
Old 03-05-2011, 06:08 AM   #8
Aquarius_Girl
Senior Member
 
Registered: Dec 2008
Posts: 4,731

Original Poster
Blog Entries: 29

Rep: Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940
but you didn't comment on the second highlighted thing, that was my major concern.
 
Old 03-05-2011, 06:25 AM   #9
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by Anisha Kaul View Post
but you didn't comment on the second highlighted thing, that was my major concern.
I have a habit of posting unfinished answers then hitting edit a few times to finish. That has saved me from loosing too much in many network failures, etc. But it has the drawback as you saw this time that someone sees the unfinished answer and thinks that was all I wrote.

So please reread the above answer. But there wasn't much to say about that highlighted code other than it is wrong.

Edit: Looking at three different posts you wrote with highlighted things, maybe I misunderstand what you mean by "second".

If you mean
Code:
(class_instance->*method)(parameter)
My comment on that was implied within my suggestion to read a tutorial on "pointer to member". Such tutorial would include all three strange syntaxes associated with pointer to member.

The pointer declaration, such as
(Class :: *Method)(Parameter)

The pointer value, such as
&B :: methodB

The use of the pointer, such as
(class_instance->*method)(parameter)

Last edited by johnsfine; 03-05-2011 at 06:42 AM.
 
Old 03-05-2011, 10:47 AM   #10
Steve K.
LQ Newbie
 
Registered: Jul 2004
Location: Portland, OR
Posts: 15

Rep: Reputation: 1
Another link: http://www.partow.net/programming/te...ack/index.html
 
Old 03-05-2011, 11:47 AM   #11
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by bigearsbilly View Post
also, I'm a bit rusty but, generally
initialisation lists are preferred over assignment in constructors:
Code:
 SingularCallBack (Class  * const _class_instance, Method _method):
  class_instance(class_instance),
  method(_method)
  {
    //class_instance = _class_instance;
    //method         = _method;
  }
http://www.parashift.com/c++-faq-lit....html#faq-10.6
I think there is a typo - an underscore is missing, it should be

Code:
class_instance(_class_instance),
.
 
Old 03-06-2011, 10:13 PM   #12
Aquarius_Girl
Senior Member
 
Registered: Dec 2008
Posts: 4,731

Original Poster
Blog Entries: 29

Rep: Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940
I will shortly address John's post, meanwhile I have got new problem here:

In the following code, the const std::string& str is what I am not able to understand. This code results in a compilation error, which I solved by removing the above highlighted &.

also, when I remove the base class's & and kept intact the derived class's &, the code compiled but didn't produce any output!

(Scroll down the code tags to see the red highlights)

This doesn't produce any errors when I remove the callback parts and keep the program
simple (i.e including base and the derived classes with the & as a parameter).

Please explain.
Code:
#include <iostream>
#include <vector>
using namespace std;

template <class MyDummyClass, typename ReturnType, typename Parameter>
class SingularCallBack
{
public:
	  typedef ReturnType (MyDummyClass ::*Method)(Parameter);
	  
	  SingularCallBack(MyDummyClass* _class_instance, Method _method)
	  {
	       class_instance = _class_instance;
	       method         = _method;
	   };

	  ReturnType execute(Parameter parameter)
	  {
	       return (class_instance->*method)(parameter);
	  };

private:
	  MyDummyClass *class_instance;
	  Method       method;
};

class BaseClass
{
   public:
     BaseClass () {}
     
     virtual bool DerivedMethod  (const std::string& str)
     {
	  return true; 
     }
};

class AClass : public BaseClass
{
public:
  AClass () {}

  bool DerivedMethod( const std::string& str)
  {
     std::cout << "Derived Method AClass: " << str << std::endl;
     return true;
  }
};

int main()
{
   std::vector < SingularCallBack < BaseClass, bool, std::string > > callback_list;

   AClass a;

   callback_list.push_back (SingularCallBack < BaseClass, bool, std::string > (&a, &BaseClass :: DerivedMethod));
   
   for (unsigned int i = 0; i < callback_list.size(); ++i)
   {
      callback_list[i].execute("abc");
   }

   return 0;
}
Compilation error:
Code:
anisha@linux-uitj:~> g++ reference.cpp -Wall -Wextra
reference.cpp:32: warning: unused parameter ‘str’
reference.cpp: In function ‘int main()’:
reference.cpp:56: error: no matching function for call to ‘SingularCallBack<BaseClass, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::SingularCallBack(AClass*, bool (BaseClass::*)(const std::string&))’
reference.cpp:11: note: candidates are: SingularCallBack<MyDummyClass, ReturnType, Parameter>::SingularCallBack(MyDummyClass*, ReturnType (MyDummyClass::*)(Parameter)) [with MyDummyClass = BaseClass, ReturnType = bool, Parameter = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]
reference.cpp:7: note:                 SingularCallBack<BaseClass, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::SingularCallBack(const SingularCallBack<BaseClass, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&)
anisha@linux-uitj:~>

Last edited by Aquarius_Girl; 03-06-2011 at 10:15 PM.
 
Old 03-07-2011, 01:12 AM   #13
Aquarius_Girl
Senior Member
 
Registered: Dec 2008
Posts: 4,731

Original Poster
Blog Entries: 29

Rep: Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940
Another question:

Template classes like above can be inherited, in which cases does it make sense to inherit them? In our software, we have a base class so on what basis should I decide whether I should
club this class with that one or I should create a new template class?
 
Old 03-07-2011, 04:17 AM   #14
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
EDIT: Nevermind.

Last edited by dwhitney67; 03-07-2011 at 06:58 AM.
 
Old 03-07-2011, 06:48 AM   #15
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by Anisha Kaul View Post
Please explain.
Code:
...
     virtual bool DerivedMethod  (const std::string& str)
...
   std::vector < SingularCallBack < BaseClass, bool, std::string >  > callback_list;
...
   callback_list.push_back (SingularCallBack < BaseClass, bool, std::string > (&a, &BaseClass :: DerivedMethod));
Compilation error:
The compilation error meant exactly what it said. The parameter you used for DerivedMethod (std::string) did not match any parameter you declared for DerivedMethod. You only declared const std::string&

If you change those two lines
Code:
std::vector < SingularCallBack < BaseClass, bool, const std::string&  >  > callback_list;
...
callback_list.push_back (SingularCallBack <  BaseClass, bool, const std::string& > (&a, &BaseClass ::  DerivedMethod));
then it compiles.

I'm sure you're used to the fact that you can normally pass a value when a & is expected and you can normally pass a non const when a const is expected. So it is confusing that in this case you can't.

I don't know C++ well enough myself to give you a good explanation of that obscure detail. Sometimes you just need to fix what the compiler objects to even if you're not comfortable with why it objects.

Quote:
also, when I remove the base class's & and kept intact the derived class's &, the code compiled but didn't produce any output!
I'm used to getting a compiler warning for that mistake. But I haven't tested to see why you don't get it in this case. The derived class's function has a different signature than the base class's virtual function, so the derived function masks the base function rather than overriding it.

That means the base function is out of scope within the derived function. But you used &BaseClass::DerivedMethod with the derived object, so you overrode the scope to get the base class vtable entry, which points to only the base class method (because you didn't override the method).

A related tricky topic is buried in the meaning of
BaseClass::DerivedMethod
when used in the context of a derived object.

If you were to call BaseClass::DerivedMethod in the derived scope, the BaseClass:: both gets past the problem that the method has been masked out of the current scope and makes the call non virtual, so the BaseClass method is called regardless of whether that function has been overridden for the current object type.

But when you use &BaseClass::DerivedMethod that does not take the address of the above function. Instead it creates a stub function that transfers control through the vtable to the virtual function. In that case, BaseClass:: gets past the problem that the method has been masked out of the current scope and makes the address a pointer to member function rather than an ordinary pointer to function, but it does not stop the actual call from being virtual.

That strange difference between BaseClass::DerivedMethod and &BaseClass::DerivedMethod has confused a lot of C++ programmers.

Last edited by johnsfine; 03-07-2011 at 07:27 AM.
 
  


Reply

Tags
c++


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Regarding sockets and callbacks manohar Programming 1 12-21-2010 04:40 PM
gtk problem with callbacks mvan83 Programming 3 12-13-2005 06:07 PM
Callbacks in Squid s_araj Programming 2 07-02-2005 06:06 AM
callbacks in C? MylesCLin Programming 2 02-10-2005 10:27 AM
include for callbacks.c abs Programming 5 04-07-2004 02:39 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:38 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration