I'm creating a collision system for a game and having a range of bounding volume classes (AABB, OBB, 18DOP etc) and they're a child of "GameObjectElement" (abstract class). The idea being each game object can hold a vector of GameObjectElements.
The problem is if I create an AABB and attach it to a GameObject is now becomes a GameObjectElement. However, to check for a collision, I need it to be an AABB not a GameObjectElement.
My first instinct was to use casting but during university, my lecturer despised this. I've looked at polymorphism and upcasting and downcasting but can't quite piece together a solution (though I think I have all the pieces to the puzzle).
If anyone can suggest a way to fix this problem, it'd be much appreciated.
Thank you
If you want to store various members of a class hierarchy, you usually use pointers. (Other possibilities are variants and 'chameleon classes' of same size). This is because vectors need to store elements of the same type and size. What you need here is a pure virtual function for collision checking (e.g. virtual bool collision(const int x, const int y) = 0) in the base class, an implementation of that virtual function in each descendant (e.g., virtual bool collision(const int x, const int y) { return x == m_x && y==m_y; }) and to store pointers to base in the vector (e.g. std::vector<GameObjectElement*> v). Then - miracle happens :) - calling v[i]->collision(x, y) will call the apropriate implementation in the descendant. Be sure to allocate elements with new and deallocate with delete - or just use shared_ptr<GameObjectElement> if you want to make it very simple in one cal.
If the selection of colission algorithm depends on the type of both instances, you are looking for a Double dispatch mechanism, which can be implemented in c++ using the Visitor pattern
The Wikipedia page actually has an example that covers collision of objects :)
https://en.wikipedia.org/wiki/Double_dispatch#Double_dispatch_is_more_than_function_overloading
Related
I have two simple classes for working with 3d geometry Point and Vector. They both have 3 coordinates as public member variables and define some operators like +, -, * ....
class Point
{
public:
double x, y, z;
// ctor and some operators
}
class Vector
{
public:
double x, y, z;
// ctor and some operators
}
Is there any real argument against making the coordiantes public?
I will never change double to any other type. I do not want to restrict the values of x, y, z to a special range and I do not want to check anything when setting the coordinates.
The classes are in a library which will be used by other projects.
Update:
For me a big disadanvtage of setters/getters would be to have to write/read code like this:
myVec.setX(myVec.x() + 1.0);
instead of
myVec.x += 1.0;
Upadate 2:
Qt uses getters/setters in QPoint but with no benefit
In C++, I will add setters and getters if only to conform to the Uniform Access Principle; why should the caller have to keep track of what is stored and what is computed?
When it comes to basic data types, where the only invariant is scope, I will happily admit that the extra effort might not be worth it. But something like a Range type (with .high, .low, .distance) where there is an invariant to be maintained (hight >= low, distance = high - low) then it's a necessity. Otherwise, all the clients of the type end up having to maintain the invariant when that should be the job of the type itself.
While at first it appears that there is no clear advantage to restrict visibility of class members, it may happen in the future.
For example, if in some future extension you want to add some attribute to the class whose value depend on the x,y,... values, it would be very valuable to have them in a private scope, so that it can get automatically re-computed.
Also, as #vandensh suggest, accessing data members through "getters" and "setters" can help detecting illegal values (see std::isnan ).
There cannot be a clear answer, it really depends on the use case.
I am a decent procedural programmer, but I am a newbie to object orientation (I was trained as an engineer on good old Pascal and C). What I find particularly tricky is choosing one of a number of ways to achieve the same thing. This is especially true for C++, because its power allows you to do almost anything you like, even horrible things (I guess the power/responsibility adage is appropriate here).
I thought it might help me to run one particular case that I'm struggling with by the community, to get a feel for how people go about making these choices. What I'm looking for is both advice pertinent to my specific case, and also more general pointers (no pun intended). Here goes:
As an exercise, I am developing a simple simulator where a "geometric representation" can be of two types: a "circle", or a "polygon". Other parts of the simulator will then need to accept these representations, and potentially deal with them differently. I have come up with at least four different ways in which to do this. What are the merits/drawbacks/trade-offs of each?
A: Function Overloading
Declare Circle and Polygon as unrelated classes, and then overload each external method that requires a geometric representation.
B: Casting
Declare an enum GeometricRepresentationType {Circle, Polygon}. Declare an abstract GeometricRepresentation class and inherit Circle and Polygon from it. GeometricRepresentation has a virtual GetType() method that is implemented by Circle and Polygon. Methods then use GetType() and a switch statement to cast a GeometricRepresentation to the appropriate type.
C: Not Sure of an Appropriate Name
Declare an enum type and an abstract class as in B. In this class, also create functions Circle* ToCircle() {return NULL;} and Polygon* ToPolygon() {return NULL;}. Each derived class then overloads the respective function, returning this. Is this simply a re-invention of dynamic casting?
D: Bunch Them Together
Implement them as a single class having an enum member indicating which type the object is. The class has members that can store both representations. It is then up to external methods not to call silly functions (e.g. GetRadius() on a polygon or GetOrder() on a circle).
Here are a couple of design rules (of thumb) that I teach my OO students:
1) any time you would be tempted to create an enum to keep track of some mode in an object/class, you could (probably better) create a derived class for each enum value.
2) any time you write an if-statement about an object (or its current state/mode/whatever), you could (probably better) make a virtual function call to perform some (more abstract) operation, where the original then- or else-sub-statement is the body of the derived object's virtual function.
For example, instead of doing this:
if (obj->type() == CIRCLE) {
// do something circle-ish
double circum = M_PI * 2 * obj->getRadius();
cout << circum;
}
else if (obj->type() == POLY) {
// do something polygon-ish
double perim = 0;
for (int i=0; i<obj->segments(); i++)
perm += obj->getSegLength(i);
cout << perim;
}
Do this:
cout << obj->getPerimeter();
...
double Circle::getPerimeter() {
return M_PI * 2 * obj->getRadius();
}
double Poly::getPerimeter() {
double perim = 0;
for (int i=0; i<segments(); i++)
perm += getSegLength(i);
return perim;
}
In the case above it is pretty obvious what the "more abstract" idea is, perimeter. This will not always be the case. Sometimes it won't even have a good name, which is one of the reasons it's hard to "see". But, you can convert any if-statement into a virtual function call where the "if" part is replaced by the virtual-ness of the function.
In your case I definitely agree with the answer from Avi, you need a base/interface class and derived subclasses for Circle and Polygon.
Most probably you'll have common methods between the Polygon and Circle. I'd combine them both under an interface named Shape, for example(writing in java because it's fresher in my mind syntax-wise. But that's what I would use if I wrote c++ example. It's just been a while since I wrote c++):
public interface Shape {
public double getArea();
public double getCentroid();
public double getPerimiter();
}
And have both Polygon and Circle implement this interface:
public class Circle implements Shape {
// Implement the methods
}
public class Polygon implements Shape {
// Implement the methods
}
What are you getting:
You can always treat Shape as a generelized object with certain properties. You'll be able to add different Shape implementations in the future without changing the code that does something with Shape (unless you'll have something specific for a new Shape)
If you have methods that are exactly the same, you can replace the interface with abstract class and implement those (in C++ interface is just an abstract class with nothing implemented)
Most importantly (I'm emphesizing bullet #1) - you'll enjoy the power of polymorphism. If you use enums to declare your types, you'll one day have to change a lot of places in the code if you want to add new shape. Whereas, you won't have to change nothing for a new class the implements shape.
Go through a C++ tutorial for the basics, and read something like Stroustrup's "The C++ programming language" to learn how to use the language idiomatically.
Do not believe people telling you you'd have to learn OOP independent of the language. The dirty secret is that what each language understands as OOP is by no means even vaguely similar in some cases, so having a solid base in, e.g. Java, is not really a big help for C++; it goes so far that the language go just doesn't have classes at all. Besides, C++ is explicitly a multi-paradigm language, including procedural, object oriented, and generic programming in one package. You need to learn how to combine that effectively. It has been designed for maximal performance, which means some of the lower-bit stuff shows through, leaving many performance-related decisions in the hands of the programmer, where other languages just don't give options. C++ has a very extensive library of generic algorithms, learning to use those is required part of the curriculum.
Start small, so in a couple year's time you can chuckle fondly over the naïveté of your first attempts, instead of pulling your hair out.
Don't fret over "efficiency," use virtual member functions everywhere unless there is a compelling reason not to. Get a good grip on references and const. Getting an object design right is very hard, don't expect the first (or fifth) attempt to be the last.
First, a little background on OOP and how C++ and other languages like Java differ.
People tend to use object-oriented programming for several different purposes:
Generic programming: writing code that is generic; i.e. that works on any object or data that provides a specified interface, without needing to care about the implementation details.
Modularity and encapsulation: preventing different pieces of code from becoming too tightly coupled to each other (called "modularity"), by hiding irrelevant implementation details from its users.
It's another way to think about separation of concerns.
Static polymorphism: customizing a "default" implementation of some behavior for a specific class of objects while keeping the code modular, where the set of possible customizations is already known when you are writing your program.
(Note: if you didn't need to keep the code modular, then choosing behavior would be as simple as an if or switch, but then the original code would need to account for all of the possibilities.)
Dynamic polymorphism: like static polymorphism, except the set of possible customizations is not already known -- perhaps because you expect the user of the library to implement the particular behavior later, e.g. to make a plug-in for your program.
In Java, the same tools (inheritance and overriding) are used for solving basically all of these problems.
The upside is that there's only one way to solve all of the problems, so it's easier to learn.
The downside is a sometimes-but-not-always-negligible efficiency penalty: a solution that resolves concern #4 is more costly than one that only needs to resolve #3.
Now, enter C++.
C++ has different tools for dealing with all of these, and even when they use the same tool (such as inheritance) for the same problem, they are used in such different ways that they are effectively completely different solutions than the classic "inherit + override" you see in Java:
Generic programming: C++ templates are made for this. They're similar to Java's generics, but in fact Java's generics often require inheritance to be useful, whereas C++ templates have nothing to do with inheritance in general.
Modularity and encapsulation: C++ classes have public and private access modifiers, just like in Java. In this respect, the two languages are very similar.
Static polymorphism: Java has no way of solving this particular problem, and instead forces you to use a solution for #4, paying a penalty that you don't necessarily need to pay. C++, on the other hand, uses a combination of template classes and inheritance called CRTP to solve this problem. This type of inheritance is very different from the one for #4.
Dynamic polymorphism: C++ and Java both allow for inheritance and function overriding, and are similar in this respect.
Now, back to your question. How would I solve this problem?
It follows from the above discussion that inheritance isn't the single hammer meant for all nails.
Probably the best way (although perhaps the most complicated way) is to use #3 for this task.
If need be, you can implement #4 on top of it for the classes that need it, without affecting other classes.
You declare a class called Shape and define the base functionality:
class Graphics; // Assume already declared
template<class Derived = void>
class Shape; // Declare the shape class
template<>
class Shape<> // Specialize Shape<void> as base functionality
{
Color _color;
public:
// Data and functionality for all shapes goes here
// if it does NOT depend on the particular shape
Color color() const { return this->_color; }
void color(Color value) { this->_color = value; }
};
Then you define the generic functionality:
template<class Derived>
class Shape : public Shape<> // Inherit base functionality
{
public:
// You're not required to actually declare these,
// but do it for the sake of documentation.
// The subclasses are expected to define these.
size_t vertices() const;
Point vertex(size_t vertex_index) const;
void draw_center(Graphics &g) const { g.draw_pixel(shape.center()); }
void draw_outline()
{
Derived &me = static_cast<Derived &>(*this); // My subclass type
Point p1 = me.vertex(0);
for (size_t i = 1; i < me.vertices(); ++i)
{
Point p2 = me.vertex(1);
g.draw_line(p1, p2);
p1 = p2;
}
}
Point center() const // Uses the methods above from the subclass
{
Derived &me = static_cast<Derived &>(*this); // My subclass type
Point center = Point();
for (size_t i = 0; i < me.vertices(); ++i)
{ center += (center * i + me.vertex(i)) / (i + 1); }
return center;
}
};
Once you do that, you can define new shapes:
template<>
class Square : public Shape<Square>
{
Point _top_left, _bottom_right;
public:
size_t vertices() const { return 4; }
Point vertex(size_t vertex_index) const
{
switch (vertex_index)
{
case 0: return this->_top_left;
case 1: return Point(this->_bottom_right.x, this->_top_left.y);
case 2: return this->_bottom_right;
case 3: return Point(this->_top_left.x, this->_bottom_right.y);
default: throw std::out_of_range("invalid vertex");
}
}
// No need to define center() -- it is already available!
};
This is probably the best method since you most likely already know all possible shapes at compile-time (i.e. you don't expect the user will write a plug-in to define his own shape), and thus don't need any of the whole deal with virtual. Yet it keeps the code modular and separates the concerns of the different shapes, effectively giving you the same benefits as a dynamic-polymorphism approach.
(It is also the most efficient option at run-time, at the cost of being a bit more complicated at compile-time.)
Hope this helps.
Thanks in advance for the replies.
store() is a function of Backpack class which is holding an array of pointers (Item * items). The arguments sent to store() are correct (tested by printing them out with cout). displayInventory() still prints the previous Item object's members at the end of the function.
void store(string & name, float weight, int power, int slot)
{
items[slot] = new Weapon(name, weight, power); // Weapon is a derived class of Item
this->displayInventory();
}
Thanks.
EDIT: Researching vectors now.
First, here are a couple of things which might ease your life (and the life of those who will read your code). It would simplify your code. Hence it will make easier to understand and debug:
Use relevant names for your variables.
Example:
void store(string & name, float weight, int power, int slot)
{
items[slot] = new Weapon(name, weight, power);
numItems+=1;
this->getInventory();
}
Use relevant / consistent names for your methods.
Here, it's hard to understand what is the purpose of getInventory() because it starts with get, yet its return type isvoid. (Maybe you meant buildInventory()?)
You don't need to redefine in your derive class, what is already in the base class.
In particular you don't need to redefine name, weight and power (and their getters) in Weapon, since it's already defined in Item
If you don't define any constructor in a class, the compiler will provide a default one without arguments.
It means you can remove the line Container(){;}
Don't reinvent the wheel. You'd better use a std::vector rather than trying to handling yourself pointers and arrays.
I'm pretty sure this last advice can by itself fix your issue. In particular, if you use a vector<Item>, you won't need to manipulate pointers yourself anymore. It means no more new and no more delete.
I find this question very interesting after reading the part of "Effective C++" about public inheritance. Before it would be common sense for me to say yes, because every square is a rectangle, but not necessarily other way around. However consider this code:
void makeBigger(Rectangle& r) {
r.setWidth(r.width() + 10);
}
This code is perfectly fine for a Rectangle, but would break the Square object if we passed it to makeBigger - its sides would become unequal.
So how can I deal with this? The book didn't provide an answer (yet?), but I'm thinking of a couple of ways of fixing this:
Override setWidth() and setHeight() methods in Square class to also adjust the other side.
Drawback: code duplication, unnecessary 2 members of Square.
For Square not to inherit from Rectangle and be on its own - have size, setSize() etc.
Drawback: weird - squares are rectangles after all - it would be nice to reuse Rectangle's features such as right angles etc.
Make Rectangle abstract (by giving it a pure virtual destructor and defining it) and have a third class that represents rectangles that are not squares and inherits from Rectangle. That will force us to change the above function's signature to this:
void makeBigger(NotSquare& r);
Can't see any drawbacks except having an extra class.
Is there a better way? I'm leaning towards the third option.
This is one of the key principles in OO design that I find gets handled incorrectly. Mr Meyer does an excellent job of of discussing it the book you are referring to.
The trick is to remember that the principles must be applied to concrete use cases. When using inheritence, remember that the key is that the "is a" relationship applies to an object when you want to use that object as a ... So whether a square is a rectangle or not depends on what you are going to be doing with rectangles in the future.
If you will be setting width and height of a rectangle independently, then no, a square is not a rectangle (in the context of your software) although it is mathematically. Thus you have to consider what you will be doing with your base objects.
In the concrete example you mention, there is a canonical answer. If you make makeBigger a virtual member function of rectangle, then each one can be scaled in a way that is appropriate to a class. But this is only good OO design if all the (public) methods which apply to a rectangle will apply to a square.
So let's see how this applies to your efforts so far:
I see this kind of thing in production code pretty often. It's excusable as a kludge to fix a gap in an otherwise good design, but it is not desirable. But it's a problem because it leads to code which is syntactically correct, but semantically incorrect. It will compile, and do something, but the meaning is incorrect. Lets say you are iterating over a vector of rectangles, and you scale the width by 2, and the height by 3. This is semantically meaningless for a square. Thus it violates the precept "prefer compile time errors to runtime errors".
Here you are thinking of using inheritance in order to re-use code. There's a saying "use inheritance to be re-used, not to re-use". What this means is, you want to use inheritance to make sure the oo code can be re-used elsewhere, as its base object, without any manual rtti. Remember that there other mechanisms for code re-use: in C++ these include functional programming and composition.
If square's and rectangles have shared code (e.g. computing the area based on the fact that they have right angles), you can do this by composition (each contains a common class). In this trivial example you are probably better off with a function though, for example:
compute_area_for_rectangle(Shape* s){return s.GetHeight() * s.GetWidth());}
provided at a namespace level.
So if both Square and Rectangle inherit from a base class Shape, Shape having the following public methods: draw(), scale(), getArea() ..., all of these would be semantically meaningful for whatever shape, and common formulas could be shared via namespace level functions.
I think if you meditate on this point a little, you'll find a number of flaws with your third suggestion.
Regarding the oo design perspective: as icbytes mentioned, if you're going to have a third class, it makes more sense that this class be a common base that meaningfully expresses the common uses. Shape is ok. If the main purpose is to draw the objects than Drawable might be another good idea.
There are a couple other flaws in the way you expressed the idea, which may indicate a misunderstanding on your part of virtual destructors, and what it means to be abstract. Whenever you make a method of a class virtual so that another class may override it, you should declare the destructor virtual as well (S.M. does discuss this in Effective C++, so I guess you would find this out on your own). This does not make it abstract. It becomes abstract when you declare at least one of the methods purely virtual -- i.e. having no implementation
virtual void foo() = 0; // for example
This means that the class in question cannot be instantiated. Obviously since it has at least one virtual method, it should also have the destructor declared virtual.
I hope that helps. Keep in mind that inheritence is only one method by which code can be re-used. Good design comes out of the optimal combination of all methods.
For further reading I highly recommend Sutter and Alexandrescu's "C++ Coding Standards", especially the section on Class Design and Inheritence. Items 34 "Prefer composition to inheritence" and 37 "Public inheritence is substitutability. Inherit, not to reuse, but to be reused.
It turns out the easier solution is
Rectangle makeBigger(Rectangle r)
{
r.setWidth(r.width() + 10);
return r;
}
Works perfectly well on squares, and correctly returns a rectangle even in that case.
[edit]
The comments point out that the real problem is the underlying call to setWidth. That can be fixed in the same way:
Rectangle Rectangle::setWidth(int newWidth) const
{
Rectangle r(*this);
r.m_width = newWidth;
return r;
}
Again, changing the width of a square gives you a rectangle. And as the const shows, it gives you a new Rectangle without changing the existing Rectangle The previous function now becomes even easier:
Rectangle makeBigger(Rectangle const& r)
{
return r.setWidth(r.width() + 10);
}
Except from having an extra class there are no serious drawbacks of your 3rd solution (called also Factor out modifiers). The only I can think of are:
Suppose I have a derived Rectangle class with one edge being a half of the other, called for example HalfSquare. Then according to your 3rd solution I'd have to define one more class, called NotHalfSaquare.
If you have to introduce on more class then let it be rather Shape class both Rectangle, Square and HalfSquare derive from
If you want your Square to be a Rectangle, it should publicly inherit from it. However, this implies that any public methods that work with a Rectangle must be appropriately specialised for a Square. In this context
void makeBigger(Rectangle& r)
should not be a standalone function but a virtual member of Rectangle which in Square is overridden (by providing its own) or hidden (by using makeBigger in the private section).
Regarding the issue that some things you can to do a Rectangle cannot be done to a Square. This is a general design dilemma and C++ is not about design. If somebody has a reference (or pointer) to a Rectangle that actually is a Square and want to do an operation that makes no sense for a Square, then you must deal with that. There are several options:
1 use public inheritance and make Square throw an exception if an operation is attempted that is not possible for a Square
struct Rectangle {
double width,height;
virtual void re_scale(double factor)
{ width*=factor; height*=factor; }
virtual void change_width(double new_width) // makes no sense for a square
{ width=new_width; }
virtual void change_height(double new_height) // makes no sense for a square
{ height=new_height; }
};
struct Square : Rectangle {
double side;
void re_scale(double factor)
{ side *= factor; } // fine
void change_width(double)
{ throw std::logic_error("cannot change width for Sqaure"); }
virtual void change_height(double)
{ throw std::logic_error("cannot change height for Sqaure"); }
};
This really is awkward and not appropriate if change_width() or change_height() are integral parts of the interface. In such a case, consider the following.
2 you can have one class Rectangle (which may happen to be square) and, optionally, a separate class Square that can be converted (static_cast<Rectangle>(square)) to a Rectangle and hence act as a Rectangle, but not be modified like a Rectangle
struct Rectangle {
double width,height;
bool is_square() const
{ return width==height; }
Rectangle(double w, double h) : width(w), height(h) {}
};
// if you still want a separate class, you can have it but it's not a Rectangle
// though it can be made convertible to one
struct Square {
double size;
Square(Rectangle r) : size(r.width) // you may not want this throwing constructor
{ assert(r.is_square()); }
operator Rectangle() const // conversion to Rectangle
{ return Rectangle(size,size); }
};
This option is the correct choice if you allow for changes to the Rectangle that can turn it into a Square. In other words, if your Square is not a Rectangle, as implemented in your code (with independently modifiable width and height). However, since Square can be statically cast to a Rectangle, any function taking an Rectangle argument can also be called with a Square.
You say: "because every square is a rectangle" and here the problem lies exactly. Paraphrase of famous Bob Martin's quote:
The relationships between objects are not shared by their
representatives.
(original explanation here: http://blog.bignerdranch.com/1674-what-is-the-liskov-substitution-principle/)
So surely every square is a rectangle, but this doesn't mean that a class/object representing a square "is a" class/object representing a rectangle.
The most common real-world, less abstract and intuitive example is: if two lawyers struggle in the court representing a husband and a wife in the context of a divorce, then despite the lawyers are representing the people during a divorce and being currently married they are not married themselves and are not during a divorce.
My idea:
You have a superclass, called Shape. Square inherits from Shape. It has the method resize(int size ). A Rectangle is ClassRectangle, inheriting from Shape but implementing interface IRecangle. IRectangle has method resize_rect(int sizex, int size y ).
In C++ interfaces are created by the usage of so called pure virtual methods. It is not fully well implemented like in c# but for me this is even better solution than third option. Any opinions ?
I have a class hierarchy with the following three classes:
template<int pdim >
class Function
{
virtual double operator()( const Point<pdim>& x) const = 0;
};
Which is a function in pdim-dimensional space, returning doubles.
template<int pdim, int ldim >
class NodeFunction
{
virtual double operator()( const Node<pdim,ldim>& pnode, const Point<ldim>& xLoc) const = 0;
};
Which is a function from the ldim-dimensional local space of a node in pdim-dimensional space.
template<int pdim, int ldim, int meshdim >
class PNodeFunction
{
virtual double operator()( const PNode<pdim,ldim,meshdim>& pnode, const Point<ldim>& xLoc) const = 0;
};
Reason 1 for this design: a NodeFunction is more general than a Function. It can always map the local ldim-point point to a pdim-point. E.g an edge (Node with ldim=1) maps the interval [0,1] into pdim-dimensional physical space. That is why every Function is a NodeFunction. The NodeFunction is more general as the NodeFunction is allowed to query the Node for attributes.
Reason 2 for this design: a PNodeFunction is more general than a NodeFunction. Exactly one Node is accociated to every PNode (not vice versa). That is why every PNodeFunction is a NodeFunction. The PNodeFunction is more general as it also has all the context of the PNode which is part of a Mesh (thus it knows all its parents, neighbours, ...).
Summary: Every Function<pdim> is a NodeFunction<pdim, ldim> for any parameter of ldim. Every NodeFunction<pdim, ldim> is a NodeFunction<pdim, ldim, meshdim> for any parameter of meshdim.
Question: What is the best way to express this in C++, such that I can use Function in place of NodeFunction / PNodeFunction, such that the code is fast (it is a high performance computing code), such that the Code works for
The template parameters are not completely independent but rather dependend on each other:
- pdim=1,2,3 (main interest) but it is nice if it works also for values of pdim up to 7.
- 'ldim=0,1,...,pdim'
- 'meshdim=ldim,ldim+1,...,pdim'
To consider the performance, note that obly a few functions are created in the program, but their operator() is called many times.
Variants
I thought about a few ways to implement this (I currently implemented Variant 1). I wrote it down here so that you can tell me about the advanage and disadvantage of these approaches.
Variant 1
Implement the above described inheritance A<dim> inherits from B<dim,dim2> via a helper template Arec<dim,dim2>. In pseudo Code this is
class A<dim> : public Arec<dim,dim>;
class Arec<dim,dim2> : public Arec<dim,dim2-1>, public B<dim,dim2>;
class Arec<dim,0> : public B<dim,dim2>;
This is applied both to inherit Function from NodeFunction and NodeFunction from PNodeFunction. As NodeFunction inherits roughly O(pdim^2) times from PNodeFunction how does this scale? Is this huge virtual table bad?
Note: In fact every Function should also inherit from VerboseObject, which allows me to print debugging information about the function to e.g. std::cout. I do this by virtually inheritung PNodeFunction from VerboseObject. How will this impact the performance? This should increase the time to construct a Function and to print the debug information, but not the time for operator(), right?
Variant 2
Don't express the inheritance in C++, e.g. A<dim> doesn inherit from B<dim,dim2> bur rather there is a function to convert the two
class AHolder<dim,dim2> : public B<dim, dim> {
}
std::shared_pointer< AHolder<dim,dim2> > interpretAasB( std::shared_pointer< AHolder<dim> >)
[...]
This has the disadvanate that I can no longer use Function<dim> in place of NodeFunction<dim> or PNodeFunction<dim>.
Variant 3
What is your prefered way to implement this?
I don't comprehend you problem very well; that might be because I lack specific knowledge of the problem domain.
Anyway it seems like you want to generate a hierarchy of classes, with Function (most derived class) at the bottom, and PNodeFunction at the top (least derived class).
For that I can only recommend Alexandrescu's Modern C++ design book, especially the chapter on hierarchy generators.
There is an open source library stemming from the book called Loki.
Here's the part that might interest you.
Going the generic meta-programming way might be the hardest but I think it will result in ease of use once setup, and possibly increased performance (that is always to be verified by the profiler) compared to virtual inheritance.
In any case I strongly recommend not inheriting from the Verbose object for logging, but rather having a separate singleton logging class.
That way you don't need the extra space in the class hierarchy to store a logging object.
You could have only the least derived class inherit from the Verbose object but your function classes are not logging objects; they use a logging object (I may be a bit pedantic here). The other problem is if you inherit multiple times from that base class, you'll end up with multiple copies of the logging object and have to use virtual inheritance to solve it.