Click here to Skip to main content
15,888,286 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi all,

Is there any way to assign member-function of a class A to member-function-pointer of another class B; and then call then call that member function of class A using member-function-pointer of class B?

C++
//IN MyParser.h
class CMyParser					//CLASS B
{
public :
	void (*pfnWithinParse)(int  i);
	void Parse(string& sFileName)
	{
		......

		if( m_pfnWithinParse )
			m_pfnWithinParse(0);
		......
	}
};


//IN ExternalUser.h
#include "MyParser.h"

class CExternalUser				//CLASS A
{
public :
	void Use(void)
	{
		CMyParser parser;
		parser.pfWIthinParse = CExternalUser::NonStaticFn;
		parser.Parse();
	}

	void NonStaticFn(int passed)	{}
};


I want to call non-static function NonStaticFn() of class A in class B member function; How shall I do it?

Please let me know if any solution exist for above situation, without abstract class (/interface) or degelate in C++?

Thanks & Regards,
Aniket
Posted
Updated 30-May-12 0:02am
v2
Comments
[no name] 30-May-12 7:43am    
As soon as you arrive at this point you know there is something wrong with the design. No ifs, buts or maybes.

If you want to call a non-static function (that is a method) of a class, then you need an instance of that class.
 
Share this answer
 
Comments
nv3 30-May-12 7:17am    
Absolutely correct. Either you create an instance of class CExternalUser and use it to call the member function via the pointer or (if CExternalUser has non data members) then why do you insist in calling a non-static function.
CPallini 30-May-12 7:49am    
Thank you.
In addition to what CPallini said the type of function pointer you want to store the address of the member function in is wrong - without a fairly heavyweight cast (i.e. a reinterpret_cast - the mallet of all casts) you'll never get that assignment to work. And even if you did it'd just crash and burn messily.

It's a fairly common idiom to store a pointer to an object and the operation to be carried out on the object in another object. I know you said you didn't want to use a delegate, but, that's the sort of thing you're going to have to do:
C++
class B;

class A
{
    public:
        A( B *object, void (B::*function)( int ) )
            : object_( object ), function_( function ){}

        void do_something( int n )
        {
            if( object_ && function_ ) (object_->*function_)( n );
        }

    private:
        void (B::*function_)( int );
        B *object_;
};

class B
{
    public:
        void do_something( int n )
        {
            std::cout << n << std::endl;
        }
};

int main()
try
{
    B b;
    A a( &b, &B::do_something );

    a.do_something( 27 );
}
catch( std::exception &e )
{
    std::cout << "Something went wrong: " << e.what() << std::endl;
}
catch(...)
{
    std::cout << "Something went wrong, no idea what!" << std::endl;
}
This gives you two axes of variation for customising A. As an example this works really well for bundling up abstract factories into "ordinary" factory methods.

Perhaps if you gave us a bit more information about what you want to do (i.e. what the problem is you're trying to solve, not the solution you're trying) someone might be able to suggest something that does the same thing in idiomatic C++.
 
Share this answer
 
Comments
Andy Rama 2-Jun-12 2:50am    
Hi Aescleal and all,

Thanks for reply.

Considering that my question is not understandable, below I am explaining it again.
I wanted to design a class or library for parsing any xml-file, named as CXmlParser. This class will have a function ParseXml() to perform actual xml-file parsing. Along with it another class, CXmlTag, to store every xml-tag data.

An external module/application, class name as CExternalCaller, will use above mentioned class/library to parse any xml-file.

CExternalCaller will call ParseXml() of CXmlParser.
Then CXmlParser will do the parsing. But code/action for start-tag and end-tag will not be residing in CXmlParser class.
Instead of that external module i.e. CExternalCaller should decide that behaviour. So any other module/application using same parsing (CXmlParser) can have different behaviour.

This was my problem definition. Interface implementation for CXmlParser (class with pure virtual function) can be one of the solution for it.
But I was trying to implement it using member-function-pointers (for StartTag & EndTag indication) in CXmlParser class which will store addresses of respective functions of caller, i.e. CExternalCaller. There were many problems when I was trying to implement this solution.

Thanks Aescleal, I took help from your post & implement it using template and function-pointer as follows.

//XmlParser
class CXmlParser
{
public :
template<class CALLER>
void ParseXml(const string& rsXmlFile, CALLER* pCaller, void (CALLER::*pfStartTag)(CXmlTag* pTag), void (CALLER::*pfEndTag)(CXmlTag* pTag) );
};

template<class CALLER>
void CXmlReader::ParseXml(const string& rsXmlFile, CALLER* pCaller, void (CALLER::*pfStartTag)(CXmlTag* pTag), void (CALLER::*pfEndTag)(CXmlTag* pTag) )
{
.....
CXmlTag* pXmlTag = new CXmlTag();
.....
//START OF XML-TAG
if( pCaller && pfStartTag )
(pCaller->*pfStartTag)(pXmlTag);
.....
//END OF XML-TAG
if( pCaller && pfEndTag )
(pCaller->*pfEndTag)(pXmlTag);
.....
}



//ExternalCaller
class CExternalCaller
{
public :
void GetData()
{
....
//READ DATA FROM XML
CXmlParser xmlParser;
xmlParser.ParseXml("<xml-file-path>", this, &CExternalCaller::StartTag, &CExternalCaller::EndTag);
....
}

private :
void StartTag(CXmlTag* pTag) {}
void EndTag(CXmlTag* pTag) {}
}



At least now its working as per my requirement. Please let me know if I am wrong anywhere in problem definition or approach.

Thanks & Regards,
Aniket
Hi Prasad!

Let's use friend class concept.
Make friend of Class A to Class B, And then u can access member function and data members of Class B into Class A.

Regards
Arjun
 
Share this answer
 
Comments
enhzflep 30-May-12 6:57am    
Certainly, that will grant access to non-public methods/variables, though as CPallini pointed out - you still need ClassB to contain an instance of ClassA in order to access a (non-static) member of ClassA.
Aescleal 30-May-12 7:49am    
Friend isn't a panacea in this case. It's perfectly possible to call public member functions of A from B and vice-versa without needing to resort to friends.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900