Getting around base class constructor initialization, a bad habit? - c++

I have a base class in an OpenGL project which represents 3DModel in general. Now I want to create a more specialized class that will inherits from 3DModel. My problem is the mandatory base class constructor call in the initialization list. Is there a proper way to delay this call until I've done some computation in the derived constructor?
Here's the important parts of the code:
class 3DModel {
public:
3DModel(std::vector<...> vertices){ ... };
[...]
private:
std::vector<...> vertices;
[...]
};
class Cylinder : public 3DModel {
public:
Cylinder(float top_bottom_ratio, float base_diameter);
[...]
};
//.cpp
Cylinder(float top_bottom_ratio, float base_width)
:3DModel(...) //<---- Mandatory
{
//I would like to calculate the cylinder vertices here
//and then feed them to the 3DModel constructor
}
Right now, I'm thinking of creating a dummy 3DModel() constructor and then call methods inside the derived constructor to modify the attributes of the base class. But this sounds really weird and it'll create a danger zone in the constructor where the object will be invalid for a few moment.
Another solution would be to thrash this class and simply do the computation inside the main program and use 3DModel constructor. But this is a sad solution and ruins the black-box approach.
Do you have any insights?

You can put the calculation into a helper function. Ideally, make it static, so you can't accidentally access unititialized base class values.
class Cylinder : public 3DModel {
public:
Cylinder(float top_bottom_ratio, float base_diameter);
[...]
private:
static calculateVertices(std::vector<...> vertices);
};
//.cpp
Cylinder(float top_bottom_ration, float base_width)
:3DModel(calculateVertices(top_bottom_ratio, base_width))
{
}
std::vector<...> Cylinder::calculateVertices(float top_bottom_ratio, float base_width) {
// calculate and return vertices here
}
You could also opt for composition instead of inheritance, where Cylindar has a 3DModel instead of being a 3DModel. (It would probably need to be something else, e.g. a Renderable that has a render() method.)

This is an example of the classic question of base-subclass vs composite. While the answer does give an example in the form of "base class - subclass", you really have to ask if this can't just be a class 'Cylinder' that contains the '3DModel' class. Unless your Cylinder subclass (and any other subclass) really adds more functionality to the 3DModel class, you really should make Cylinder a composite of the 3DModel class.

Related

derived class of a base class functioning as an abstract class

I have defined a super class element. There are some derived class of element say triangle , quad and cube. Some of the element objects are boundary element. If the element is boundary element, then I have to define additional data members and functions. I could have easily derive a boundary_element class if the element class is not base class.(What I meant is, if triangle , quad and cube are separate classes I can define separate derived classes like boundary_triangle , boundary_quad , andboundary_cube).
So my problem is I have to define a subclass boundary_element which has to be the base (or even abstract) class for defining derived classes boundary_quad , boundary_triangle and boundary_cube.
Is this somehow possible in C++? could anyone suggest any architecture which serves the purpose?
Another way I can solve my problem according to my logic is, define a class like below:
class boundary_element
{
element* m_boundary_elem;
//data members needed for quad,triangle and cube
public:
boundary (element*);
//functions for modifying data's of triangle,cube,quad.
}
The element pointer is defined as member variable of another class. How do I restructure this class effectively using inheritance. ( i.e Function it as an abstract class, for deriving boundary_triangle , boundary_quad, and boundary_cube class )
I don't know my question is weird but as a beginner I'm really confused how to use inheritance properly. Sorry if my heading is misleading.
C++ has multiple inheritance, so you can derive from Element and Boundary at the same time and avoid code duplication.
Something like this:
class Element {
};
class Boundary {
};
class Triangle : public Element {
};
class BoundaryTriangle : public Triangle, public Boundary {
};
. . .
Is this somehow possible in C++?
Of course it is.
could anyone suggest any architecture which serves the purpose?
Something along these lines:
Have an abstract base class and interface
class AbstractShape {
boundary getBoundary() const = 0;
void draw(OutputScreen& screen) const = 0;
};
Have implementations for particular shapes like
Triangle : public AbstractShape {
// Implement the triangle specifics
};
Rectangle : public AbstractShape {
// Implement the rectangle specifics
};
Circle : public AbstractShape {
// Implement the circle specifics
};

How can I decide at runtime which derived class to use as a private class member in C++?

This following question is a bit hard for me to formulate, but please bear with me, and let me know if I can help in clearing anything up.
I am writing a general-purpose simulation for 3D shapes. I am using a base class:
class Shape{
public:
...
virtual double return_volume() =0;
private:
vector<double> coordinates;
...
};
Now, since I don't know what shape the user will choose, I derive several classes from this. (e.g.: Sphere, Cube, Tetrahedron, etc.)
So far, everything is fine.
The main problem comes in the form that I have a Controller class, which launches and operates the simulation. As a private member, it should have a vector of multiple shapes (all of the same type. e.g.: 15 spheres, or 10 cubes, etc.)
class SimulationControl{
public:
void runsimulation();
private:
vector<Shape> all_shapes;
...
};
I wanted to simply initialize this private member with a non-default constructor.
Now, before I knew what I had done, Eclipse already told me that "The type 'Shape' must implement the inherited pure virtual method 'Shape::return_volume'"
I understand the error message and my mistake, of course, but I still don't understand how I can solve it.
What I would love to be able to do is to leave the type of vector undefined, and then simply create it via the constructor with the correct derived class at runtime, when I know which type of simulation the user chose.
Is is somehow possible to do that? Thanks
I'm not going to jump on the bandwagon and suggest using pointers in your container, whether smart or dumb. This is the perfect opportunity to use the PIMPL idiom.
The idea is that the class is simply a wrapper for the actual implementation, and calls a pointer to another object when a call is made to it. The pointer contained within the wrapper can be polymorphic so that it can implement the functions however it sees fit.
class Shape{
public:
Shape() { pImpl = NULL; }
Shape(const Shape& from) { pImpl = from.pImpl->clone(); }
~Shape() { delete pImpl; }
Shape& operator=(const Shape& from) { pImpl = from.pImpl->clone(); }
...
double return_volume() { return pImpl->return_volume(); }
private:
ShapeImpl * pImpl;
...
};
class ShapeImpl{
public:
...
virtual ShapeImpl* clone() const =0;
virtual double return_volume() =0;
private:
vector<double> coordinates;
...
};
Because the Shape class contains a pointer you'll need to implement the rule of three and create a destructor, copy constructor, and operator=. The defaults for the copies will certainly do the wrong thing - they'll only copy the pointer value without creating a new copy of the pimpl object to go with them. Since a vector copies elements around these functions are certain to get called.
Use (smart) pointers.
You cannot instantiate an abstract class, and even if you could, that would probably not be what you want, since you wouldn't be able to create aliases of those shapes.
You should change the definition of your SimulationControl class into something more similar to this (assuming shared ownership for your shapes here - if SimulationControl is the only owner of your shapes, rather use unique_ptr instead of shared_ptr):
#include <memory>
class SimulationControl {
public:
void runsimulation();
private:
std::vector<std::shared_ptr<Shape>> all_shapes;
...
};
Then, you could create instances of your shapes and add them to the all_shapes collection as follows (supposing MyShape is a concrete, default-constructible class derived from Shape):
std::shared_ptr<MyShape> pShape = std::make_shared<MyShape>();
pShape->set_vertices(...); // I guess the class will have a member function
// that allows setting the shape's vertices...
all_shapes.push_back(pShape);
You can only do polymorphism by pointer or reference. Try using vector<Shape*>.
Now that you are using pointers you'll have to manage the memory for them, but that is another set of questions. Try to use smart pointers if you can, or be very careful if you can't. If you are using C++11, std::vector<std::unique_ptr<Shape>> might fit the bill for you.

Calling a function which belongs to another class

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
};

C++ class extension (different size of array in inheriting classes)

I am new to C++, i would like to get an advice.
I am writing two classes that contain both an array of the same object but with different size. Both of the classes has the same methods to deal with the array, but each has it's own unique behavior. Because of that, i would like to create a new class to represent the array and the operations on it, and to make these two classes extend it.
For example:
Class classA{
Person* persons[5];
string className;
...
}
Class classB{
Person* persons[15];
int integerForClassB;
string className;
...
}
What is the best (most suggested) way to define the class parentClass such that it will deal only with the pesrons array and that classA will extend parentClass (with array of size 5) and classB will extend parentClass (with array of size 15)?
Does something like this help? Using an STL vector of type Person, you can make the base class take a count for the number of persons. Then each derived class calls the base class constructor with a different size for the m_persons vector. The vector in each case will then be filled to the requested size with default-initialised instances of Person.
include
class Person
{
};
class ParentClass
{
public:
// Relies on Person having a default constructor
ParentClass( int personCount ) : m_persons( personCount )
{
}
private:
std::vector<Person> m_persons;
};
class ClassA : public ParentClass
{
public:
ClassA() : ParentClass(5)
{
}
};
class ClassB : public ParentClass
{
public:
ClassB() : ParentClass(15)
{
}
};
Do you need to extend the array handling class? Maybe it is better to just use that class from ClassA and ClassB. Prefer composition over inheritance
Do you need an array? As others have said a std::vector could be better.
In case you need the array, have you thought on using templates? A class template can have integer arguments like
template <int npersons> class PersonHandler {
Person* persons[npersons]
}
so you can inherit ClassA from PersonHandler<5> and ClassB from PersonHandler<15>. But note that the PersonClass is a different class for ClassA and ClassB.
Based on the question, my thought is that the best way is to not use inheritance. Use public inheritance to define a class hierarchy. Be very cautious when using it as a means of code reuse, as more often than not, composition is the superior option.
As suggested in the comments, consider a std::vector.
If std::vector does not have all of the desired operations, check if <algorithms> fulfills your needs.
If your needs are still not fulfilled, consider writing collection operations as free functions instead of member functions. With proper decoupling, these operations can work on std::vector<Person> or arrays of Person.
If you must have a collection of Persons with very specific behavior, then use composition. The question description implies composition is correct: "two classes that contain both an array..."
With regards to inheritance, if classA is-a collection-ofPersons and classB is-a collection-ofPersons, then consider public inheritance, if the set of common methods, that different in behavior, can uphold a common set of pre-conditions and post-conditions. For example, consider an Ellipse and Circle:
class Ellipse
{
// Set the width of the shape.
virtual void width( unsigned int );
// Set the height of the shape.
virtual void height( unsigned int );
};
class Circle
{
// Set the width of the shape. If height is not the same as width, then
// set height to be equal to width.
virtual void width( unsigned int );
// Set the height of the shape. If width is not the same as height, then
// set width to be equal to height.
virtual void height( unsigned int );
};
It is very tempting to have Circle derive from Ellipse:
Outside of programming, one could argue that Circle is a special kind of Ellipse, just like a Square is a special kind of Rectangle.
They even have the same member functions: width() and height().
However, do not do it! Ellipse can do things a Circle cannot do, such as having a different width and height; therefore Circle should not be a kind of Ellipse.

How to avoid code repetition and wasting memory with const members and inheritance?

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