Function inheritance

A

Alex Vinokur

Hi,

I need something like "function inheritance".

typedef void (*func_type1) (int);
typedef int (*func_type2) (double);
typedef char (*func_type3) (short, int);
....

I need a vector contains pointers to functions of types above.

Because conceptions "base function" and "derived function" are missing in C++,
it seems that the problem (of creating the vector) should be resolved
by using special base and derived classes/structures.

struct BFunc
{
// Stuff
};


struct DFunc1
{
func_type1 func_;
DFunc1 (func_type1 f) : func_ (f) {}
// Stuff
};

struct DFunc2
{
func_type2 func_;
DFunc2 (func_type2 f) : func_ (f) {}
// Stuff
};

struct DFunc3
{
func_type3 func_;
DFunc3 (func_type3 f) : func_ (f) {}
// Stuff
};

Now, we have

vector<*BFunc> v;

And, for instance
v.push_back (new DFunc2 (f));
v.push_back (new DFunc1 (ff));
v.push_back (new DFunc3 (fff));
v.push_back (new DFunc2 (ffff));
v.push_back (new DFunc1 (fffff));


The questions are:
1) Do we have to use dynamic_cast (while processing vector<*BFunc>)
to call a relevant function via v?
2) Is there any better solution of the "function inheritance" problem?
 
I

Ivan Vecerina

Alex Vinokur said:
I need something like "function inheritance".

typedef void (*func_type1) (int);
typedef int (*func_type2) (double);
typedef char (*func_type3) (short, int);
...

I need a vector contains pointers to functions of types above.

Because conceptions "base function" and "derived function" are missing in
C++,
it seems that the problem (of creating the vector) should be resolved
by using special base and derived classes/structures.

I have trouble understanding the concept of function inheritance.
To talk about inheritance, you need IMO a common interface between
the 'parent' and 'child'. If the functions, as above, have
incompatible interfaces, how can you interact with the 'child'
as if it were a 'parent' ?
How are the functions above more compatible/related to each
other than any other function ? What makes them a "family" ?

[snip: creating wrapper classes]
The questions are:
1) Do we have to use dynamic_cast (while processing vector<*BFunc>)
to call a relevant function via v?
2) Is there any better solution of the "function inheritance" problem?


All (non-member) function pointers can safely be converted
to e.g. void(*)() and back. IIRC this may require
a reinterpret_cast (not just a static cast) though,
and is safe if you don't call the function until the
pointer is cast back to its original type.
Rather than void(*)(), it might therefore be safer to
use a function that you won't be able to call (e.g.
because it takes an undefined type as a parameter).

What I would use is:

typedef void (*any_func)(class ThisClassDoesNotExist&);
std::vector<any_func> myFunctions;


hth,
Ivan
 
A

Alf P. Steinbach

* Alex Vinokur:
Hi,

I need something like "function inheritance".

typedef void (*func_type1) (int);
typedef int (*func_type2) (double);
typedef char (*func_type3) (short, int);
...

I need a vector contains pointers to functions of types above.

As Ivan Vecerina wrote, the above seems to be unrelated function
signatures.


Because conceptions "base function" and "derived function" are missing in C++,
it seems that the problem (of creating the vector) should be resolved
by using special base and derived classes/structures.

struct BFunc
{
// Stuff
};


struct DFunc1
{
func_type1 func_;
DFunc1 (func_type1 f) : func_ (f) {}
// Stuff
};

Why not make the function itself a member function?

operator() is provided for that purpose.

Then an object of this class will be a functor object.


struct DFunc2
{
func_type2 func_;
DFunc2 (func_type2 f) : func_ (f) {}
// Stuff
};

struct DFunc3
{
func_type3 func_;
DFunc3 (func_type3 f) : func_ (f) {}
// Stuff
};

Now, we have

vector<*BFunc> v;

And, for instance
v.push_back (new DFunc2 (f));
v.push_back (new DFunc1 (ff));
v.push_back (new DFunc3 (fff));
v.push_back (new DFunc2 (ffff));
v.push_back (new DFunc1 (fffff));

The questions are:
1) Do we have to use dynamic_cast (while processing vector<*BFunc>)
to call a relevant function via v?


For that you need at least one virtual function.

2) Is there any better solution of the "function inheritance" problem?

It's difficult to see what you're trying to achieve since your
function signatures are all different (need different arguments).

What are you intending to use this for?

Most probably that's where the real problem/solution is, whereas this
"function inheritance" stuff is probably particular to an imagined but
ungood solution.
 
A

Alex Vinokur

Ivan Vecerina said:
I have trouble understanding the concept of function inheritance.
To talk about inheritance, you need IMO a common interface between
the 'parent' and 'child'. If the functions, as above, have
incompatible interfaces, how can you interact with the 'child'
as if it were a 'parent' ?
How are the functions above more compatible/related to each
other than any other function ? What makes them a "family" ?
[snip]

It seems that code below is what I want to.

========= foo.cpp : BEGIN =========
#include <cassert>
#include <cstdlib>
#include <iostream>
#include <string>
#include <map>
using namespace std;

typedef int (*func_type1) (int);
typedef int (*func_type2) (int, int);

int f1 (int x) { return (10 * x + 1); }
int f2 (int x, int y) { return (10 * x + 10 * y + 2); }
int f3 (int x) { return (10 * x + 3); }


// -------------------------
struct BFunc
{
static map<string, BFunc*> store_s;
static void init_store_fs ();
static void free_store_fs ();
virtual int get_value (int, char**) const = 0;
virtual ~BFunc() {}
};
map<string, BFunc*> BFunc::store_s;


struct DFunc1 : public BFunc
{
const func_type1 func_;
DFunc1 (const func_type1& func_i) : func_ (func_i) {}
int get_value (int argc, char** argv) const
{
assert (argc >= 3);
return func_ (atoi (argv[2]));
}
};


struct DFunc2 : public BFunc
{
const func_type2 func_;
DFunc2 (const func_type2& func_i) : func_ (func_i) {}
int get_value (int argc, char** argv) const
{
assert (argc >= 4);
return func_ (atoi (argv[2]), atoi (argv[3]));
}
};


// ------
const string name1 ("a1");
const string name2 ("a2");
const string name3 ("a3");


void BFunc::init_store_fs ()
{
store_s[name1] = new DFunc1 (f1);
store_s[name2] = new DFunc2 (f2);
store_s[name3] = new DFunc1 (f3);
}


void BFunc::free_store_fs ()
{
for (map<string, BFunc*>::iterator pos_iter = store_s.begin();
pos_iter != store_s.end();
pos_iter++
)
{
delete pos_iter->second;
}
}



int main (int argc, char** argv)
{
BFunc::init_store_fs ();
assert (argc >= 2);

const string name(argv[1]);
if (BFunc::store_s.count(name))
{
cout << BFunc::store_s[name]->get_value (argc, argv) << endl;
}
else
{
cout << name << " is not in store" << endl;
}

BFunc::free_store_fs ();

return 0;
}
========= foo.cpp : END ===========



========= Compilation & Run : BEGIN =========

$ gpp --version
gpp.exe (GCC) 3.4.1
[---omitted---]

$ gpp -W -Wall foo.cpp
// No errors/warnings


$ a.exe a1 3 // function f1 is invoked; its type is func_type1
31

$ a.exe a2 3 4 // function f2 is invoked; its type is func_type2
72

$ a.exe a3 3 // function f3 is invoked; its type is func_type1
33

$ a.exe a4
a4 is not in store

========= Compilation & Run : END ===========
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,184
Messages
2,570,976
Members
47,536
Latest member
MistyLough

Latest Threads

Top