delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2000/03/14/19:56:08

From: lied AT w-lied DOT ih DOT lucent DOT com (Robert Lied)
Newsgroups: comp.os.msdos.djgpp
Subject: Re: TABLE OF POINTERS TO FUNCTIONS + OTHER
Date: 14 Mar 2000 23:21:27 GMT
Organization: Lucent Technologies, Naperville, Illinois, USA
Lines: 87
Message-ID: <8amhhn$cvu@ssbunews.ih.lucent.com>
References: <8am435$j8i$1 AT tron DOT sci DOT fi>
NNTP-Posting-Host: w-lied.ih.lucent.com
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

In article <8am435$j8i$1 AT tron DOT sci DOT fi>, Traveler <traveler AT netti DOT fi> wrote:
>I tried to make a table that can store pointers to any kind of functions
>like the one below.
>void     func(void);
>int        func2(int,int);
>long     func3(int);
>void*    table[ ] = {func,func2,func3};
>So, what do I have to do to make a table of varied function pointers ?

You'll have to give the compiler more type information --
uses casts when you invoke the function.  Try something like this:

typedef void (*FPTR_V_V)(void);	/* ptr to func returning void, no args */
typedef int  (*FPTR_I_II)(int, int);  /* return int, takes two ints */
typedef long (*FPTR_L_I)(int);	/* ptr to func that takes int, returns long */
...
(*(FPTR_I_II)(table[1])(5, 6);

Beyond that, you might reconsider why you want a table of
heterogenous functions.  Would function overloading do as well?

	void func(void) { ... }			// Function A
	int  func(int x, int y) { ... }	// Function B
	long func(int x) { ... }		// Function C
	...
	// Calls Function B because two int parameters match its signature
	func(5, 6)

A more object-oriented approach might be to use a functor object,
which only exists to give an object handle to a function.  Consider
this:

class Action {
	public:
		virtual long do_it(void) = 0;
	};

// In place of void func(void)
class NoArgAction: public Action {
	public:
		long do_it(void) { func(); return 0; }

	private:
		void func(void) { /* What func did */ system("cat /dev/null"); }
	};

// In place of int func2(int, int)
class IntArgsAction : public Action {
	public:
		long do_it(void) { return func2(i1, i2); }

		IntArgsAction(int x, int y) : i1(x), i2(y) { }
		void setArgs(int x, int y) { i1 = x ; i2 = y; }
	private:
		int i1, i2;
		long func2(int x, int y) { /* What func2 did */ return x + y; }
	};

// In place of long func3(int)
class IntAction : public Action {
	public:
		long do_it(void) { return func3(i1); }

		IntAction(int x) : i1(x) { }
		void setArgs(int x) { i1 = x; }
	private:
		int i1;
		long func3(int x) { /* What func3 did */ return x * 7; }
	}

// A lot of setup, but here comes the elegant payoff.
//  Functions become objects
NoArgAction   func;
IntArgsAction func2(5, 6);  // Or set parameters later with setArgs
IntAction     func3(0);

// Table of pointers to functors, using base class
Action *table[] = { &func, &func2, &func3 };

int
reactToEvent(int event)
{
	// Resolves to derived class because do_it() is virtual
	return table[event]->do_it();
};

---------

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019