Sorry for the larger amount of the source code. There three abstract classes P, L, PL. The third class PL is derived from classes P and L using the virtual inheritance:
template <typename T> //Abstract class
class P
{
public:
virtual ~P() = 0;
virtual P <T> *clone() const = 0;
};
template <typename T>
P<T>::~P() {}
template <typename T>
P<T> * P <T>:: clone() const { return new P <T> ( *this ); }
template <typename T> //Abstract class
class L
{
public:
virtual ~L() = 0;
virtual L <T> *clone() const = 0;
};
template <typename T>
L<T>::~L() {}
template <typename T>
L<T> *L <T> ::clone() const { return new L <T> ( *this );}
template <typename T>
class PL: virtual public P <T>, virtual public L <T> //Abstract class
{
public:
PL() : P <T>(), L<T>() {}
virtual ~PL() = 0;
virtual PL <T> *clone() const = 0;
};
template <typename T>
PL<T>::~PL() {}
template <typename T>
PL<T> * PL <T> :: clone() const { return new PL <T> ( *this );}
Every class has its own implementation of the clone method.
Two next classes PA, PC are derived from class P using the virtual inheritance:
template <typename T>
class PC : virtual public P <T>
{
public:
PC() : P <T> () {}
virtual ~PC() {}
virtual PC <T> *clone() const {return new PC <T> ( *this );}
};
template <typename T>
class PA : virtual public P <T>
{
public:
PA() : P <T> () {}
virtual ~PA() {}
virtual PA <T> *clone() const {return new PA <T> ( *this );}
};
The last two classes PCL and PAL are dirived using the virtual inheritance from PC and PL , PA and PL.
template <typename T>
class PCL : public PC <T>, public PL <T>
{
public:
PCL() : P <T> (), PC <T> (), PL <T> () {}
virtual ~PCL() {}
virtual PCL <T> *clone() const {return new PCL <T> ( *this );}
};
template <typename T>
class PAL : public PA <T>, public PL <T>
{
public:
PAL() : P <T> (), PA <T> (), PL <T> () {}
virtual ~PAL() {}
virtual PAL <T> *clone() const {return new PAL <T> ( *this );}
};
There is the diagram of the class dependencies:
.......... P .... L.....
........../|\..../......
........./.|.\../.......
......../..|..\/........
.......PC..PA..PL.......
.......|...|.../|.......
.......|...|../.|.......
.......|...PAL..|.......
.......|........|.......
.......PCL_____/........
Please, do not discuss this proposal :-))). I have the following 3 questions:
1) Was this class dependency rewritten in C++ correctly (first of all the placemement of "virtual")?
2) I am not sure what is wrong, see the code, please:
int main(int argc, _TCHAR* argv[])
{
PCL <double> * pcl = new PCL <double>(); //Object of abstract class not allowed
PAL <double> * pal = new PAL <double>(); //Object of abstract class not allowed
PL <double> *pl1 = pcl->clone(); //Polymorphism
PL <double> *pl2 = pal->clone(); //Polymorphism
return 0;
}
It is not possible to create new objects of PAL / PCL classes, both classes are marked as abstract. But they are not abstract. Where is the problem?
3) Is it possible to use polymorphism together with clone() method? See the code above, please...
Thanks for your help...
UPDATED QUESTION
I corrected the code. But the following error using VS 2010 compiler appear:
template <typename T> //Abstract class
class P
{
public:
virtual ~P() = 0;
virtual P <T> *clone() const = 0;
};
template <typename T>
P<T>::~P() {}
template <typename T>
P<T> * P <T>:: clone() const { return new P <T> ( *this ); }
template <typename T> //Abstract class
class L
{
public:
virtual ~L() = 0;
virtual L <T> *clone() const = 0;
};
template <typename T>
L<T>::~L() {}
template <typename T>
L<T> *L <T> ::clone() const { return new L <T> ( *this );}
template <typename T>
class PL: virtual public P <T>, virtual public L <T> //Abstract class
{
public:
PL() : P <T>(), L<T>() {}
virtual ~PL() = 0;
virtual PL <T> *clone() const = 0;
};
template <typename T>
PL<T>::~PL() {}
template <typename T>
PL<T> * PL <T> :: clone() const { return new PL <T> ( *this );}
template <typename T>
class PC : virtual public P <T>
{
protected:
T pc;
public:
PC() : P <T> () {}
virtual ~PC() {}
virtual PC <T> *clone() const {return new PC <T> ( *this );}
};
template <typename T>
class PA : virtual public P <T>
{
public:
PA() : P <T> () {}
virtual ~PA() {}
virtual PA <T> *clone() const {return new PA <T> ( *this );}
};
template <typename T>
class PCL : public PC <T>, public PL <T>
{
public:
PCL() : P <T> (), PC <T> (), PL <T> () {}
virtual ~PCL() {}
virtual PCL <T> *clone() const {return new PCL <T> ( *this );}
}; //Error using VS 2010: Error 1 error C2250: 'PCL<T>' : ambiguous inheritance of 'PC<T> *P<T>::clone(void) const'
template <typename T>
class PAL : public PA <T>, public PL <T>
{
public:
PAL() : P <T> (), PA <T> (), PL <T> () {}
virtual ~PAL() {}
virtual PAL <T> *clone() const {return new PAL <T> ( *this );}
}; //Error VS 2010: Error 1 error C2250: 'PAL<T>' : ambiguous inheritance of 'PA<T> *P<T>::clone(void) const'
int main(int argc, char* argv[])
{
PCL <double> * pcl = new PCL <double>();
PAL <double> * pal = new PAL <double>();
PL <double> *pl1 = pcl->clone();
PL <double> *pl2 = pal->clone();
return 0;
}
Maybe i overlooked something... But g++ compiles this code OK.
Just some small errors in your code:
Get the base initializers right:[Sorry, that was wrong -- you do have to call the virtual base constructor because of the virtual inheritance.] you do have to say the round parentheses.PAL() : PC <T>(), PL <T>() {}
There is no initialization ofP<T>
, which isn't a direct base; butDeclare pure virtual functions without definition:
virtual L <T> *clone() const = 0;
Double-check that you want
PL
to inherit virtually fromP
but non-virtually fromL
(but that's fine).Double-check that all your
clone()
s have the same constness.If you already have one pure virtual function in your abstract base class, you should not make the destructor pure. Instead, say,
virtual ~T() { }
. Otherwise you should still provide a definition of the pure virtual destructor (because the destructor always needs to be callable):virtual T::~T() { }
There are a couple of typos which need fixing in your code, but the
virtual
s in the inheritance lattice are correct. (They're the minimum. You can add more; in the rare cases where such lattices occur, it's often best to make all inheritance virtual, to protect against future evolution.)There's nothing wrong with your test code. Once the typos in the original are fixed, it compiles fine with g++.
It's possible, and it should work the way you've done it.
This compiles for me using VC10:
Note that I had to remove
PL <T> *PL <T>::clone()
to get VC to accept the code. The problem with that is that, if you have aPL<T>
, and call it'sclone()
, it will statically return anL<T>*
, rather than aPL<T>*
, even though the dynamic type is of a class derived fromPL<T>
.Because the clone method in your P class is abstract as it is defined
(btw that {} is incorrect). What you have to understand is that once this template is instantiated this is a separate method with a completely different signature from the derive classes clone method. template instantiation creates behaves as if it generates new code. Thus this is a pure abstract method that never got implemented. Thus making everyone that inherits this method (every derived class) an abstract class.
Edit: As for the third question. Run time and compile time polymorphism dont mix well. I have no idea why on earth you want to use such a complex structure but I am sure that the design can be simplified far far more.
MSVC doesn't support co-variant returns properly. Where you think you've been overriding the function, actually you've just been hiding it. That's the problem at hand.