Template subclass virtual override

D

Dewdman42

I have a question for C++ gurus

Assuming I have template class:

template <class T>
class Car<T>
{
Car();
virtual T* factory();
}

template <class T>
T*
Car::factory()
{
return new T;
}


Here is a class I will use to drive T above:

class Airplane
{
Airplane();
}

To use like this:

Car<Airplane> myCar;
Airplane* a = myCar.factory();

Fine so far. Now let's say I want to subclass my template to provide
an ovreride to the factory method because I don't want to allow a
default constructor of Airplane, but rather a one arg constructor:

class Spaceship
{
Spaceship(int arg);
private:
Spaceship(); // to prevent being able to instantiate without
arg
}

And finally a subclass of the template that overrides the virtual
factory method:

class Boat : public Car<Spaceship>
{
Boat();
virtual Spaceship* factory();
}


Spaceship*
Boat::factory()
{
return new Spaceship(100);
}

In theory to use like this:

Boat<Spaceship> myBoat;
Spaceship* a = myBoat.factory();


The above does not quite compile because when the compiler uses
Spaceship to generate the Boat<Airplane> class from the template,
which is really a subclass of Car, it expects to find a default
constructor for the Spaceship class in order to satisfy the template
base class virtual factory method, even though there are no clients
that will use Car<Spaceship>, only Boat<Spaceship>

I really need Car() to have this default factory method for cases
where people will not use a subclass or override that virtual factory
method, like my first example of Car<Airplane>. However, I also in
this case don't want to provide a default constructor to my Spaceship
class because it will NEVER be used that way and I want to make sure
it can't be used that way.

Can anyone think of a way to satisfy the template without having to
add the default constructor to Spaceship? Or perhaps a different
class structure that will accomplish what I'm trying to do. ??
 
N

Neelesh Bodas

I have a question for C++ gurus

Assuming I have template class:

The code posted is far far awaty from being a compilable code.
template <class T>
class Car<T>
{
Car();
virtual T* factory();

Everything in this class is private. Not in sync with the way 'Car' is
used in your remaining code.

missing semicolon.
template <class T>
T*
Car::factory()

Doesnot compile. Car is a template class said:
{
return new T;
}

Here is a class I will use to drive T above:

class Airplane
{
Airplane();
}
private constructor - not in sync with usage of Airplane below. Also
missing semicolon.
To use like this:

Car<Airplane> myCar;
Can't instantiate, Car constructor is private
Airplane* a = myCar.factory();
Can't call, factory() is private
Fine so far. Now let's say I want to subclass my template to provide
an ovreride to the factory method because I don't want to allow a
default constructor of Airplane, but rather a one arg constructor:

class Spaceship
{
Spaceship(int arg);
private:
Spaceship(); // to prevent being able to instantiate without

Everything here is private, no need of that label. Further, you don't
need to declare a non-arg constructor as private if you have declared
one-arg constructor.
arg
}
missing ;
And finally a subclass of the template that overrides the virtual
factory method:

class Boat : public Car<Spaceship>
{
Boat();
virtual Spaceship* factory();

}
Everything private, missing ;
Spaceship*
Boat::factory()
{
return new Spaceship(100);
}

In theory to use like this:

Boat<Spaceship> myBoat;

Boat is _not_ a template class. You cant use it like this. Further,
Boat constructor is private
Spaceship* a = myBoat.factory();

Boat::factory is private
The above does not quite compile because when the compiler uses
Spaceship to generate the Boat<Airplane> class from the template,
which is really a subclass of Car, it expects to find a default
constructor for the Spaceship class in order to satisfy the template
base class virtual factory method, even though there are no clients
that will use Car<Spaceship>, only Boat<Spaceship>

Assuming that all the above errors are taken care of, observe that the
constructor Boat() will need the class Car<Spaceship> to get
instantiated. The class Car<T> has a virtual function factory(). Acc.
to 14.7.1(9): "It is unspecified whether or not an implementation
implicitly instantiates a virtual member function of a class template
if the virtual member function would not otherwise be instantiated".
If your compiler decides to instantiates the virtual member function,
that attempt will fail since there is no Spaceship::Spaceship()
constructor. (public of course).


I really need Car() to have this default factory method for cases
where people will not use a subclass or override that virtual factory
method, like my first example of Car<Airplane>. However, I also in
this case don't want to provide a default constructor to my Spaceship
class because it will NEVER be used that way and I want to make sure
it can't be used that way.

Can anyone think of a way to satisfy the template without having to
add the default constructor to Spaceship? Or perhaps a different
class structure that will accomplish what I'm trying to do. ??

Please post code that compiles. That will help.
 
D

Dewdman42

Please post code that compiles. That will help.

Thanks a lot. I actually just tried a different approach which is
still not ideal, but will get my problem solved with only a tiny hole
that I have to provide a default constructor in Spaceship even though
I don't really want to. I didn't completely understand the paragraph
you copied from the C++ spec unfortunately, but at this point I'm
betting on its just not possible to do what I hoped and that's it. I
am also trying to backwards-support a pre-existing Car<> class which
already has clients in production...and I want the <T> class to be any
arbitrary class with no requirements such as being derived from some
interface. I was hoping I could avoid the requirement of a default
constructor always being present in <T>, but it appears that is the
one requirement I have to support.

Note - I wasn't trying to provide compilable code, just enough to
express the higher level concept of what I'm trying to accomplish.

Thanks again.
 

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,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top