I have a (guaranteed tree-shaped) cascade of classes like
class rock_bottom {
...
virtual foo() = 0;
};
class A : rock_bottom {...}
class intermediate: rock_bottom {...}
class B : intermediate {...}
class higher_up {...}
class C : higher_up {...}
I want to implement foo() in the lettered classes A, B, C. Where do I need to declare foo? (Virtual? Pure?) Do I need (trivial) implementations in the middle layers intermediate and higher_up?
Question:
I want to implement foo() in the lettered classes A, B, C. Where do I need to declare foo? (Virtual? Pure?)
Answer:
That question needs to be asked in reverse. In which base class does it make sense to create the interface foo. Let's take some classes that you might find in application.
struct Shape {};
struct Rectangle : public Shape {};
struct Square : public Rectangle {};
struct Ellipse : public Shape {};
struct Circle : public Ellipse {};
It makes sense that all Shape be able to return their area and perimeter. So you put them as virtual member functions in Shape.
struct Shape
{
virtual double area() const = 0;
virtual double perimeter() const = 0;
};
Before you can create an instance of sub-type of Shape, you must implement them.
If you want to be able to create a Rectangle, those functions must be implemented in Rectangle since there are no other intermediate classes.
If you want to be able to create a Square, those functions must be implemented either in Rectangle, Square, or both.
Similarly, if you want to be able to create a Ellipse, those functions must be implemented in Ellipse since there are no other intermediate classes.
If you want to be able to create a Circle, those functions must be implemented either in Ellipse, Circle, or both.
However, only Rectangles have length and width. Only Ellipses have major radius and minor radius. It doesn't make sense to add virtual member functions in Shape to return those values.
Question:
Do I need (trivial) implementations in the middle layers intermediate and higher_up?
Answer:
No, you don't. The answer to the previous question should clarify that more.
Each override needs to be declared in the class that implements it; in your case, A, B and C, since you say each will provide an override.
There's no need to declare it in any intermediate class, assuming you're happy for them to remain abstract. They inherit the pure function from rock_bottom, and there's no point overriding that with another pure function.
Related
Let's say I have
struct Transformable {
virtual void mirror()=0;
}
class Shape: public Transformable {
Position position;
Color color;
public:
virtual void draw()=0; // 0. <-this, or
virtual void draw(); // I. <-this, or
void draw(); // II. <-this, or maybe
// III. <-this?
}
class Circle {
double radius;
public:
void mirror();
}
(Where Transformable is the abstract class A, Shape is the "intermediary" class B, and Circle is C.)
Which should I use from the cases I-III (noted in //comments above)?
It doesn't make sense for Shape to have a function mirror(), so I would not want to write any code there, choosing option 0 over III.
If I would want to write code, I'd choose I over II.
If I'm right, why? If not, why?
Edit: I need class Shape for a heterogeneous collection, and I made a class Transformable to have transform functions separate from everything. Also I chose to have it go through Shape because this way I don't have to type
AnyShape: public Transformable, public Shape
only
AnyShape: public Shape
Usually, the virtual keyword is only used in the base class. You can omit it in all derived classes and the method will nevertheless be virtual. You can still use it, but it doesn't add much except maybe for readability. Usually, in the derived classes, the keyword override is preferred for overridden virtual methods, because it will check at compile time that you actually override something. So you (usually) have:
class Base{
virtual void method();
};
class Derived : public Base {
void method() override; // still virtual
};
As for the = 0, you add it everywhere that there is no implementation, or where you want to force for a derived non abstract class (i.e. a class you want to instantiate in your code) to implement/override a certain method.
Note that override is only available if you use C++11 and above.
virtual void draw() = 0;
virtual void draw();
are both valid ways declaring the function in Shape.
The choice of whether to use the first one or the second one can be made based on what you expect Shape to do and what you expect its sub-types to do (Circle is the only one you have shown but there will be more I reckon).
If you expect that Shape can take care of some aspects of draw() but the derived classes must have their own implementation, then use the first option. Implement Shape::draw(). Derived classes can make use of Shape::draw() in their implementation.
If you expect that Shape can take care of all aspects of draw() for some classes, then use the second option. In this case, only those derived classes that need to override the function will override it and those that don't need to can leave it out of their implementation.
My suggestion will be to go with the first option. If there are some derived classes that don't need to do anything, they can call Shape::draw() and do nothing more. E.g.
class StrangeShape : public Shape
{
public:
void draw() override { Shape::draw(); }
};
I am creating an application that allows a user to define dimensions for different shapes and returns the area to the user using the dimensions they specified.
My base class is Shape. Derived classes are Triangle, Circle, Square and Rectangle.
I have created an array of Shape in the hope of creating and storing instances of any of the derived classes in the array during runtime.
Shape** shape = new Shape*[TOTAL_SHAPES];
shape[i] = new Circle(radius);
I have managed this, however I am unable to access the instantiated classes methods. Sorry if this is a stupid question I am fairly new to C++.
Let's assume your types had the following definition
class Shape {
public:
void Method1() { ... }
};
class Circle : public Shape {
void Method2() { ... }
}
With this definition you could access methods on Shape by doing the following
shape[i]->Method1();
In this context though it wouldn't be possible to access Method2 though because the compiler only knows about Shape, not Circle.
shape[i]->Method2(); // Error!
You have three options:
Make Shape an abstract base class and call virtual methods that are members of Shape
Use static_cast to cast from a Shape* to a Circle*, and call methods through that.
Use dynamic_cast to cast from a Shape* to a Circle*, and call methods through that.
The first option is likely best in many cases. Among other reasons, you almost surely need to have a virtual destructor (which can be a by-product of making Shape an ABC), and you may prefer to not have to know what type of object is being pointed to, rather you'd like to simply call methods on whatever it may be. If you can use this idiom, use it.
The second option is dangerous. You must absolutely know that the object being pointed to is a Circle (or whatever) in order to use static_cast, else you will get Undefined Behavior.
The third option is only possible if your class is polymorphic, which means Shape must have at least one virtual method. You surely should have a virtual destructor, and this would serve that purpose.
How about that:
shape[i]->aMethod();
For starters, I highly recommend using a smart pointer wrapper instead of using raw pointers (especially if you are new to the language).
std::vector<std::shared_ptr<Shape>> shapes(TOTAL_SHAPES);
That will define a vector with an initial size of TOTAL_SHAPES.
To the root of your problem, any method you wish to call using a Shape* must be valid for Shape, or you must do a risky downcast to the appropriate type. For example:
class Shape
{
public:
// constructors and other methods go here
virtual ~Shape() { } // virtual destructor
virtual void Draw() { } // virtual function to be used by derived classes
};
class Circle
{
public:
// ...
virtual ~Circle() { }
virtual void Draw() { } // override the virtual function
};
Then, in your application code,
std::vector<std::shared_ptr<Shape>> shapes(TOTAL_SHAPES);
shapes[0] = std::make_shared(new Circle);
shapes[0]->Draw(); // calls Circle::Draw
Note that depending on your usage, std::unique_ptr may replace std::shared_ptr.
I'm working on a university assignment about finding the array of different shapes using OOP.
I have created all of my shape classes so they derive from my main Shape Class. Shape class is being used like an interface, so that all the shape classes derived from the shape class have to have a calculate area function, etc.
I want to create an array of different shapes. I have declared an array with a type of shape, which is the parent class and i want to add new instances of each different shape, circle, square, rectangle and triangle to the array list so that all the information about each shape is stored in one array. I have the follow code but i have an error on the line aShapes[i] = square; saying that shape is an inaccessible base of square.
If anyone could help out that would be great.
Thanks in advanced.
Here is my code
#include <cstdlib>
#include <iostream>
#define M_PI 3.14159265358979323846
using namespace std;
class Shape{
public:
string sName;
float nArea;
void fnAddData();
float fnCalculateArea();
};
class Square : private Shape {
private:
float nSide;
void fnAddData()
{
cout << "Please enter the length of a side: ";
cin >> nSide;
}
float fnCalculateArea(float side)
{
return (side * side);
}
public:
Square()
{
sName = "Square";
fnAddData();
nArea = fnCalculateArea(nSide);
}
};
Shape aShapes[5];
/*
*
*/
int main(int argc, char** argv)
{
int decision;
Square square;
for (int i = 0; i < 5; i++)
{
cout << "Shape number";
cin >> decision;
switch (decision)
{
case 1:
aShapes[i] = square;
}
}
return 0;
}
Arrays aren't polymorphic: Everything stored in the array must be the same type. Your array of Shape won't work.1
So how do you get polymorphism when using an array, then? Change your array to store pointers to Shape:
Shape *aShapes[5];
That solves the problem nicely: A Shape* can point to a Shape or any of its descendants,2 and all the Shape* themselves are the same type.
And then in your main code, store the addresses of the objects in the array:
aShapes[i] = □
You will need to make a couple other changes to your existing code to make this work:
Use public inheritance, not private inheritance.
Make the methods in Shape virtual.
Make the methods in Square that override the interface defined by Shape public.
Add a virtual destructor.
1 If you do manage to copy a descendent of Shape into the array, you end up slicing the object.
2 Technicality: If you give Shape pure virtual methods, you won't be able to create an instance of a pure Shape. In that event, Shape* can't point at an instance of Shape because you can't create one! A Shape* would only point to one of its descendents that implements all of the virtual methods.
The reason you're getting that particular error is because you're using private inheritance when it looks like you really want to be using public inheritance.
class Square : public Shape {
^^^^^^
A further problem is that polymorphism works only with pointers or references. You cannot put a Square into an array of Shapes. It will simply slice out the Shape part of the Square and put that in the array. Shape aShapes[5]; is nothing more than an array of Shapes - there are no Squares, no Triangles, just Shapes. What you need is something like:
Shape* aShapes[5];
You can then set the pointers in this array to point at objects of types that derive from Shape.
You'll also need to make the functions that you want to override in the derived classes virtual. When the compiler sees something like aShapes[0]->fnCalculateArea(), and then sees that fnCalculateArea is a virtual function, it will only then look up the dynamic type of the object that aShapes[0] points to - it will then see that it's a Square and call Square::fnCalculateArea.
1) You're privately inheriting from Shape, which is more typically an undesirable form of composition. You should be publicly inheriting from Shape for your purposes.
class Square : public Shape
2) None of Shape's member functions are declared virtual, so none of them will be overridden by derived classes. You also don't have a virtual destructor. If you want the CalculateArea function of Square to be used when you call it on a Shape pointer that points to a Square, you have to declare as virtual in Shape, and override it in Square:
In Shape:
virtual float fnCalculateArea();
In Square:
void float fnCalculateArea() override;
3) If Shape should act only as an abstract interface, not to be instantiated itself, then you should make it so by making one of its functions pure virtual (the destructor at least, if nothing else).
virtual ~Shape() = 0 {}
4) If you want to store the different derived types in a single container, then you have to store them by reference, IE through a pointer to their base class.
Shape* aShapes[5];
5) I also noticed that you're prefixing many variable names with n even though they are floats. Hungarian notation typically uses n to refer to ints and f to refer to floats.
Arrays of values do NOT behave polymorphically. You will have to use an array of pointers to Shape, as access and assignment to pointers does behave polymorphically.
What you have here is object slicing, you're cutting off the Derived class chunk so that your object fits into a Base. This is bad.
With a pointer, however, you get no slicing.
Your particular error stems from use of private inheritance, which forbids conversion to the inherited class. Use public inheritance. This is just masking the issue above.
I'm just wondering if there is a way to call a function from another class which is not a derived class.
For example...
If I have class Square which has a function colour, if I have another class Triangle, totally unrealated to Square, can I somehow call the colour funciton of Square on a Triangle object?
I'm wondering if friend can be used here, but from what I have read, it can't, unless I've misunderstood what I've read.
What is the best way to implement this without creating an inheritance relationship?
If what your seeking to do is something like this:
Square s;
Triangle t;
t.colour(); // invoke Square::colour() on a Triangle
I'm sorry but you can't, unless you declare a function in Triangle which simply mimics what Square::colour does.
A wise option if you really need that function to be shared is to declare it as a standalone templated function like this:
template<typename Shape>
void colour(Shape s){
//Do stuff
}
then in order to allow this access to the inner guts of Triangle and Square, make void colour<Triangle>() and void colour<Square>() friends of the appropriate classes.
The answer is no, your request is not possible. The colour method is encapsulated within square and will not apply to an unrelated object of a difference class. Either inherit (from shape - I know you said no inheritance), or re-implement the colour method for square as well.
No, sorry to bum you out. But i would recommend using a base class 'shape', and derive shapes from this class.
class Abc //Abstract base class
{
public:
virtual ~Abc(); //destructor
virtual double Color();
virtual double Area() const = 0; //pure virtual, MUST be overridden
private:
//specific variables that apply to all shapes
};
class Square : public Abc //derived class from pure virtual class
{
public:
Square();
virtual double Color();
virtual double Area() const; //redefine color here
~Square(){}
private:
//square vars here
};
I am implementing some classes for shapes. Is there a way of avoiding code repetition and wasting memory at the same time?
Basically, I would like to have a variable in the base class that is a constant and only has one copy per derived class (like a static member), but with a different value for each derived class.
For example, I want to define functions that work on the inertia tensor for the derived classes; for each shape, the inertia tensor is a constant, so I don't want to have a copy of the same constant for every instance.
However, instead of declaring the same variable and defining the same function for every derived class, I'd like to declare a single variable at the base class and have a generic function in the base class as well, say to change the inertia tensor from world to local coordinates and vice versa.
Is there a way of accomplishing that?
Use a pure virtual function in the base class and override it in each derived class to return the appropriate value. This way you only have one copy of the constant, and each derived class defines it properly.
class Base
{
public:
virtual int get_constant0() const = 0;
};
class Derived0 : public Base
{
public:
virtual int get_constant0() const { return 5; }
};
class Derived1 : public Base
{
public:
virtual int get_constant0() const { return 42; }
};
Not related to what you asked, but related to what i think you are trying to achieve; i would start looking at existing implementations how other libraries achieve integration between rigid body types, if only to have an idea what not to do.
ODE library