K
kikazaru
Is it possible to return covariant types for virtual methods inherite
from a base class using virtual inheritance
I've constructed an example below, which has the following structure
Shape = base clas
Triangle, Square = classes derived from Shap
Prism = class derived from Shap
TriangularPrism, SquarePrism = classes derived from Triangle an
Prism, or Square and Prism respectivel
Prism provides some functionality based on virtual methods specifie
in the Shape base class instantiated in specific Shapes Triangle an
Square. Since TriangularPrism and SquarePrism inherit Shape via Pris
AND Triangle/Square, it is necessary for Prism, Triangle and Square t
inherit Shape virtually
I added a virtual Shape* clone() function to Shape, and wanted t
return Triangle* for Triangle::clone(), SquarePrism* fo
SquarePrism::clone() etc. but this did not compile. I had to retur
Shape* for every version of clone(). This means that if I clone
SquarePrism, I have to use a dynamic cast to get at the method
specific to that class
Is this right!? Is it simply impossible to use covariant return type
for methods inherited virtually from a base class?!
----------------- Code example
#include "iostream
class Shape
public
virtual double area() = 0
virtual Shape* clone() = 0
virtual char* type() { return "Shape";
}
// Shape must be inherited virtually in order to resolve multipl
inheritance in SquarePris
class Square : virtual public Shape
double length
public
Square(double l) : length(l) {
virtual double area() { return length * length;
// Use of the covariant return type Square* causes a compilatio
error because Shape is inherited virtuall
// The error reads: "sorry, unimplemented: adjusting pointer
for covariant returns
// virtual Square *clone() { return new Square(*this);
virtual Shape *clone() { return new Square(*this);
virtual char* type() { return "Square";
}
// Shape must be inherited virtually in order to resolve multipl
inheritance in TriangularPris
class Triangle : virtual public Shape
double base, height
public
Triangle(double b, double h) : base(b), height(h) {
virtual double area() { return 0.5 * base * height;
// Use of the covariant return type Triangle* causes a compilatio
error because Shape is inherited virtuall
// The error reads: "sorry, unimplemented: adjusting pointer
for covariant returns
// virtual Triangle *clone() { return new Triangle(*this);
virtual Shape *clone() { return new Triangle(*this);
virtual char* type() { return "Triangle";
}
// Shape must be inherited virtually to resolve multiple inheritanc
in SquarePrism and TriangularPris
class Prism : virtual public Shape
double depth
public
Prism(double d) : depth(d) {
double volume() { return depth * area();
virtual char* type() { return "Prism";
}
class SquarePrism : public Square, public Prism
public
SquarePrism(double d, double l) : Square(l), Prism(d) {
virtual char* type() { return "SquarePrism";
// clone cannot return a covariant return type SquarePrism* for th
same reason as Square and Triangl
virtual Shape *clone() { return new SquarePrism(*this);
}
class TriangularPrism : public Triangle, public Prism
public
TriangularPrism(double d, double b, double h) : Triangle(b,h)
Prism(d) {
virtual char* type() { return "TriangularPrism";
// clone cannot return a covariant return type TriangularPrism* fo
the same reason as Square and Triangl
virtual Shape *clone() { return new TriangularPrism(*this);
}
using namespace std
int main()
Square s(1)
Triangle t(1,1)
SquarePrism sp(10, 1)
TriangularPrism tp(10, 1, 1)
cout << "Square area = " << s.area() <
endl
cout << "Triangle area = " << t.area(
<< endl
cout << "Cloned square area = " <
s.clone()->area() << endl
cout << "Cloned triangle area = " <
t.clone()->area() << endl
cout << "Square prism volume = " <
sp.volume() << endl
cout << "Triangular prism volume = " <
tp.volume() << endl
// Causes error because volume is not a function of Shap
// cout << "Cloned square prism volume = " <<
sp.clone()->volume() << endl;
// Use dynamic cast to allow access to the Prism functions:
cout << "Cloned square prism volume = " <<
(dynamic_cast<Prism*>(sp.clone()))->volume() << endl;
return 0;
}
from a base class using virtual inheritance
I've constructed an example below, which has the following structure
Shape = base clas
Triangle, Square = classes derived from Shap
Prism = class derived from Shap
TriangularPrism, SquarePrism = classes derived from Triangle an
Prism, or Square and Prism respectivel
Prism provides some functionality based on virtual methods specifie
in the Shape base class instantiated in specific Shapes Triangle an
Square. Since TriangularPrism and SquarePrism inherit Shape via Pris
AND Triangle/Square, it is necessary for Prism, Triangle and Square t
inherit Shape virtually
I added a virtual Shape* clone() function to Shape, and wanted t
return Triangle* for Triangle::clone(), SquarePrism* fo
SquarePrism::clone() etc. but this did not compile. I had to retur
Shape* for every version of clone(). This means that if I clone
SquarePrism, I have to use a dynamic cast to get at the method
specific to that class
Is this right!? Is it simply impossible to use covariant return type
for methods inherited virtually from a base class?!
----------------- Code example
#include "iostream
class Shape
public
virtual double area() = 0
virtual Shape* clone() = 0
virtual char* type() { return "Shape";
}
// Shape must be inherited virtually in order to resolve multipl
inheritance in SquarePris
class Square : virtual public Shape
double length
public
Square(double l) : length(l) {
virtual double area() { return length * length;
// Use of the covariant return type Square* causes a compilatio
error because Shape is inherited virtuall
// The error reads: "sorry, unimplemented: adjusting pointer
for covariant returns
// virtual Square *clone() { return new Square(*this);
virtual Shape *clone() { return new Square(*this);
virtual char* type() { return "Square";
}
// Shape must be inherited virtually in order to resolve multipl
inheritance in TriangularPris
class Triangle : virtual public Shape
double base, height
public
Triangle(double b, double h) : base(b), height(h) {
virtual double area() { return 0.5 * base * height;
// Use of the covariant return type Triangle* causes a compilatio
error because Shape is inherited virtuall
// The error reads: "sorry, unimplemented: adjusting pointer
for covariant returns
// virtual Triangle *clone() { return new Triangle(*this);
virtual Shape *clone() { return new Triangle(*this);
virtual char* type() { return "Triangle";
}
// Shape must be inherited virtually to resolve multiple inheritanc
in SquarePrism and TriangularPris
class Prism : virtual public Shape
double depth
public
Prism(double d) : depth(d) {
double volume() { return depth * area();
virtual char* type() { return "Prism";
}
class SquarePrism : public Square, public Prism
public
SquarePrism(double d, double l) : Square(l), Prism(d) {
virtual char* type() { return "SquarePrism";
// clone cannot return a covariant return type SquarePrism* for th
same reason as Square and Triangl
virtual Shape *clone() { return new SquarePrism(*this);
}
class TriangularPrism : public Triangle, public Prism
public
TriangularPrism(double d, double b, double h) : Triangle(b,h)
Prism(d) {
virtual char* type() { return "TriangularPrism";
// clone cannot return a covariant return type TriangularPrism* fo
the same reason as Square and Triangl
virtual Shape *clone() { return new TriangularPrism(*this);
}
using namespace std
int main()
Square s(1)
Triangle t(1,1)
SquarePrism sp(10, 1)
TriangularPrism tp(10, 1, 1)
cout << "Square area = " << s.area() <
endl
cout << "Triangle area = " << t.area(
<< endl
cout << "Cloned square area = " <
s.clone()->area() << endl
cout << "Cloned triangle area = " <
t.clone()->area() << endl
cout << "Square prism volume = " <
sp.volume() << endl
cout << "Triangular prism volume = " <
tp.volume() << endl
// Causes error because volume is not a function of Shap
// cout << "Cloned square prism volume = " <<
sp.clone()->volume() << endl;
// Use dynamic cast to allow access to the Prism functions:
cout << "Cloned square prism volume = " <<
(dynamic_cast<Prism*>(sp.clone()))->volume() << endl;
return 0;
}