Inherited constructors (templates)

J

Johannes Bauer

Hello group,

I'm having a problem with inheritance and I've run out of ideas. I'm
trying to encpsulate threads in a nice(tm) way. Therefore I declared a
template class:

template <typename ArgumentType, typename ReturnType> class Thread

with a purely virtual method

virtual ReturnType Action() = 0;

of which my actual threads should inherit from:

class AddingThread : public Thread<int*, int> {
public:
int Action() {
int sum = 0;
for (unsigned int i = 0; i < 10; i++) {
sum += Data;
}
return sum;
}
};

Now I want to call that thing just like

int foo[10];
memset(foo, 0, sizeof(foo));
foo[5] = 9;

AddingThread t1(foo);
int result = t1.join();

The problem I get is:

threadtest.cpp: In function ‘int main()’:
threadtest.cpp:23: error: no matching function for call to
‘AddingThread::AddingThread(int [10])’
threadtest.cpp:6: note: candidates are: AddingThread::AddingThread()
threadtest.cpp:6: note: AddingThread::AddingThread(const
AddingThread&)

I can solve it, of course, by doing:

AddingThread(int *x) : Thread<int*, int>(x) { }

Where the "Thread" constructor does all the magic (i.e. actually
creating the thread and calling the trampoline to kick off "Action").
However, I do not want this redundant constructor delegation - is it
possible to tell the compiler to always use only the parent's
constructor of identical prototype if no child constructor is available?

Maybe I'm also thinking just in a very wrong way, maybe inheritance
isn't even the way to go here. Some other ideas maybe?

Kind regards,
Johannes
 
N

Neelesh

Hello group,

I'm having a problem with inheritance and I've run out of ideas. I'm
trying to encpsulate threads in a nice(tm) way. Therefore I declared a
template class:

template <typename ArgumentType, typename ReturnType> class Thread

with a purely virtual method

virtual ReturnType Action() = 0;

of which my actual threads should inherit from:

class AddingThread : public Thread<int*, int> {
        public:
                int Action() {
                        int sum = 0;
                        for (unsigned int i = 0; i < 10; i++) {
                                sum += Data;
                        }
                        return sum;
                }

};

Now I want to call that thing just like

int foo[10];
memset(foo, 0, sizeof(foo));
foo[5] = 9;

AddingThread t1(foo);
int result = t1.join();

The problem I get is:

threadtest.cpp: In function ‘int main()’:
threadtest.cpp:23: error: no matching function for call to
‘AddingThread::AddingThread(int [10])’
threadtest.cpp:6: note: candidates are: AddingThread::AddingThread()
threadtest.cpp:6: note:                 AddingThread::AddingThread(const
AddingThread&)

I can solve it, of course, by doing:

AddingThread(int *x) : Thread<int*, int>(x) { }

Where the "Thread" constructor does all the magic (i.e. actually
creating the thread and calling the trampoline to kick off "Action").
However, I do not want this redundant constructor delegation -

I'm not sure if I would call this "delegation" - You are not calling
any of the sibling constructors here, rather you are calling the
parent constructor. The parent constuctor in turn will do the work of
initializating the parent object - not the entire child object. Hence
this isn't really a "complete delegation" in that sense. The child
constructor is still needed to initialized the entire child object.
is it possible to tell the compiler to always use only the parent's
constructor of identical prototype if no child constructor is available?

No, because if a child constructor is "not available" then the child
object will not get constructed. A parent constructor can only be
called through a child constructor. If an appropriate child
constructor is not available the compiler has no way of knowing what
to call. It can't really call the "similar" parent constructor
directly, because that would only end up in initializing the base-
portion of the object being constructed.
Maybe I'm also thinking just in a very wrong way, maybe inheritance
isn't even the way to go here. Some other ideas maybe?

If you have multiple kinds of threads, say AddingThread,
SubtractingThread etc - that might be accessed using the same ABC/
interface (i.e. using an is-a relationship) then inheritance would be
an appropriate way to go. However, each of your derived classes would
need to have their own constructors. Constructors are never
inherited.
 
J

Juha Nieminen

Johannes said:
Hello group,

I'm having a problem with inheritance and I've run out of ideas. I'm
trying to encpsulate threads in a nice(tm) way. Therefore I declared a
template class:

template <typename ArgumentType, typename ReturnType> class Thread

with a purely virtual method

virtual ReturnType Action() = 0;

of which my actual threads should inherit from:

class AddingThread : public Thread<int*, int> {
public:
int Action() {
int sum = 0;
for (unsigned int i = 0; i < 10; i++) {
sum += Data;
}
return sum;
}
};

Now I want to call that thing just like

int foo[10];
memset(foo, 0, sizeof(foo));
foo[5] = 9;

AddingThread t1(foo);
int result = t1.join();

The problem I get is:

threadtest.cpp: In function ‘int main()’:
threadtest.cpp:23: error: no matching function for call to
‘AddingThread::AddingThread(int [10])’
threadtest.cpp:6: note: candidates are: AddingThread::AddingThread()
threadtest.cpp:6: note: AddingThread::AddingThread(const
AddingThread&)


I can't really understand what exactly is the problem you are seeing.
Your AddingThread class very clearly has no constructor which takes an
int pointer as parameter, which is exactly what the compiler is telling
you. The template part has nothing to do with this. Obviously the exact
same thing would happen even if the base class is not a template.
I can solve it, of course, by doing:

AddingThread(int *x) : Thread<int*, int>(x) { }

Where the "Thread" constructor does all the magic (i.e. actually
creating the thread and calling the trampoline to kick off "Action").
However, I do not want this redundant constructor delegation - is it
possible to tell the compiler to always use only the parent's
constructor of identical prototype if no child constructor is available?

In the next C++ standard it will be possible to do something like
that. In the current standard, no.
 
A

Andrew Tomazos

If an appropriate child
constructor is not available the compiler has no way of knowing what
to call. It can't really call the "similar" parent constructor
directly, because that would only end up in initializing the base-
portion of the object being constructed.

In the same way as the compiler automatically generates a default
constructor and a copy constructor, the compiler could automatically
generate "inherited constructors" with identical signatures of the
base constructors. An inherited constructor would call the base
constructor and then call the default constructor on any member
variables.

That is to say, an inherited constructor could be written explicitly
as...

class D : B
{
X1 x1; X2 x2; ... Xm xm;

D(T1 t1, T2 t2 ... Tn tn)
: B(t1,t2, ... ,tn)
, x1()
, x2()
.
.
.
, xm()
{}
};

....but would be automatically generated.
-Andrew.
 
N

Neelesh

In the same way as the compiler automatically generates a default
constructor and a copy constructor, the compiler could automatically
generate "inherited constructors" with identical signatures of the
base constructors.  An inherited constructor would call the base
constructor and then call the default constructor on any member
variables.

That is to say, an inherited constructor could be written explicitly
as...

class D : B
{
    X1 x1; X2 x2; ... Xm xm;

    D(T1 t1, T2 t2 ... Tn tn)
        : B(t1,t2, ... ,tn)
        , x1()
        , x2()
          .
          .
          .
        , xm()
    {}

};

...but would be automatically generated.
  -Andrew.

Agreed, but unfortunately not with the current standard.
 
R

Rolf Magnus

Andrew said:
In the same way as the compiler automatically generates a default
constructor and a copy constructor, the compiler could automatically
generate "inherited constructors" with identical signatures of the
base constructors.

Then there would be the need to explicitly switch this off, because you
don't always want that to happen. C++ chose the opposite way to let you
explicitly write down the constructors for your class. But it would be nice
to have at least something like a using declaration for constructors.
 

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
473,769
Messages
2,569,581
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top