Abstract base class + Functor

G

Gert Van den Eynde

Hi all,

I'm struggling a bit with Functors generated for an ABC.

This is the functor code:

class Functor{
public:
virtual double operator(double x)=0
}

template <class T> class SpecFunctor: public Functor
{
private:
double (T::*fpt)(double x);
T* obj;
}
public:
SpecFunctor(T* _obj, double(T::*_fpt)(double x))
{
obj = _obj; fpt = _fpt;
}

virtual operator()(double x)
{
(*obj.*fpt)(x);
}

Now, this works fine for 'ordinary' classes T. However, I would like to have
it working for an ABC. When I use an ABC for T, I get warnings from g++
that obj_ will get initialzed after... I more or less understand why the
warnings appear (you cannot create an object for an ABC).

It's merely warnings, but I would like to clean it up. Is there a way to do
this without giving up the Functor or ABC?

Thanks for any tips,

gert
 
T

tom_usenet

Hi all,

I'm struggling a bit with Functors generated for an ABC.

This is the functor code:

class Functor{
public:
virtual double operator(double x)=0
}

template <class T> class SpecFunctor: public Functor
{
private:
double (T::*fpt)(double x);
T* obj;
}
public:
SpecFunctor(T* _obj, double(T::*_fpt)(double x))
{
obj = _obj; fpt = _fpt;
}

virtual operator()(double x)
{
(*obj.*fpt)(x);
}

Now, this works fine for 'ordinary' classes T. However, I would like to have
it working for an ABC. When I use an ABC for T, I get warnings from g++
that obj_ will get initialzed after... I more or less understand why the
warnings appear (you cannot create an object for an ABC).

You don't show any code that tries to create an object of abstract
type.
It's merely warnings, but I would like to clean it up. Is there a way to do
this without giving up the Functor or ABC?

Once I'd fixed the syntax errors, added virtual destructors, etc., it
worked fine:

class Functor{
public:
virtual ~Functor(){}
virtual double operator()(double x) = 0;
};

template <class T>
class SpecFunctor: public Functor
{
private:
double (T::*fpt)(double x);
T* obj;
public:
SpecFunctor(T* obj, double(T::*fpt)(double x))
:eek:bj(obj), fpt(fpt)
{
}

virtual double operator()(double x)
{
return (*obj.*fpt)(x);
}
};

struct ABClass
{
~ABClass(){}
virtual double f(double d) = 0;
};

struct Derived: ABClass
{
virtual double f(double d)
{
return d * d;
}
};

#include <iostream>

int main()
{
Derived d;
Functor* f = new SpecFunctor<ABClass>(&d, &ABClass::f);
std::cout << (*f)(10) << '\n';
}

Or was that not what you meant?

Tom
 
G

Gert Van den Eynde

Or was that not what you meant?

Yes, indeed. But compiling your code with g++ -Wall gives the same warnings:


test.cc:26: warning: `struct ABClass' has virtual functions but non-virtual
destructor
test.cc:32: warning: `struct Derived' has virtual functions but non-virtual
destructor
test.cc: In constructor `SpecFunctor<T>::SpecFunctor(T*, double
(T::*)(double))
[with T = ABClass]':
test.cc:44: instantiated from here
test.cc:12: warning: `SpecFunctor<ABClass>::eek:bj' will be initialized after
test.cc:11: warning: `double (ABClass::*SpecFunctor<ABClass>::fpt)(double

The code works, as did mine, I just want to get rid of the warnings... I
suppose that when the compiler generates them, there must be a cleaner
way,no?

gert
 
A

Attila Feher

Gert said:
Yes, indeed. But compiling your code with g++ -Wall gives the same
warnings:


test.cc:26: warning: `struct ABClass' has virtual functions but
non-virtual destructor

struct ABClass
{
virtual ~ABClass(){}
virtual double f(double d) = 0;
};

TADA :)
 
G

Gert Van den Eynde

struct ABClass
{
virtual ~ABClass(){}
virtual double f(double d) = 0;
};

TADA :)

That one I figured out myself ;-) shouldn't have copy/pasted it... It's the
'will be initialized after' that I wonder about...

gert
 
D

David B. Held

Gert Van den Eynde said:
[...]
That one I figured out myself ;-) shouldn't have copy/pasted it... It's
the 'will be initialized after' that I wonder about...

template <class T>
class SpecFunctor: public Functor
{
private:
double (T::*fpt)(double x);
T* obj;
public:
SpecFunctor(T* obj, double(T::*fpt)(double x))
:eek:bj(obj), fpt(fpt)
{
}
// ...
};

The order of initialization is determined by the order of the data
members within the class, not the order of initializers in the c'tor.
Therefore, if you give a different order in the c'tor, the compiler
is warning you that it will not respect that ordering. To eliminate
the warning, make the initializer list match the data member
ordering.

Dave
 
T

tom_usenet

That one I figured out myself ;-) shouldn't have copy/pasted it... It's the
'will be initialized after' that I wonder about...

That's a good example of GCC's nanny warnings, where it annoys you by
complaining about non-errors. Change the functor to:


template <class T>
class SpecFunctor: public Functor
{
private:
double (T::*fpt)(double x);
T* obj;
public:
SpecFunctor(T* obj, double(T::*fpt)(double x))
:fpt(fpt), obj(obj) //re-ordered these
//to match the declaration order.
{
}

virtual double operator()(double x)
{
return (*obj.*fpt)(x);
}
};

Tom
 

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

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top