By mixing both static and dynamic polymorphism (templates and inheritance) I have come across a strange technique that functions similarly to regular static polymorphism in C++, except the members of the child class are still visible after creating the new object.
Consider the following example:
Base.h:
#include <iostream>
class Base {
public:
virtual ~Base() {}
virtual void say_hello() {
std::cout << "Hello from Base!" << std::endl;
}
};
Class1.h:
#include "Base.h"
#include <iostream>
class Class1 : public Base {
public:
virtual void say_hello() {
std::cout << "Hello from Class1!" << std::endl;
}
int x = 1;
};
Class2.h:
#include "Base.h"
#include <iostream>
class Class2 : public Base {
public:
virtual void say_hello() {
std::cout << "Hello from Class2!" << std::endl;
}
int y = 2;
};
This is where things get interesting...
ClassX.h
template <class T>
class ClassX : public T {
public:
int z = 3;
};
By implementing classX in such a way that it can dynamically inherit from anything it allows some strange things to occur. See the example below showing it in use.
main.cpp
#include <iostream>
#include "Base.h"
#include "Class1.h"
#include "Class2.h"
#include "ClassX.h"
using namespace std;
int main(int argc, char* argv[]) {
Base* b = new Base;
b->say_hello();
// Regular polymorphism in action
Base* c1 = new Class1;
c1->say_hello(); // Aware that this is Class1
//cout << c1->x << endl; // Doesn't work! Not visible from here
Base* c2 = new Class2;
c2->say_hello(); // Aware that this is Class2
//cout << c2->y << endl; // Doesn't work! Not visible from here
// Hyper polymorphism!? Not sure what to call this.
ClassX<Class1> cx1;
cx1.say_hello(); // Aware that this is Class1
cout << cx1.x << endl; // The member variable is visible!
cout << cx1.z << endl; // Also available :)
ClassX<Class2> cx2;
cx2.say_hello(); // Aware that this is Class2
cout << cx2.y << endl; // The member variable is visible!
cout << cx2.z << endl; // Also available :)
// ALWAYS delete objects created with "new" or shame on yew.
delete b;
delete c1;
delete c2;
}
What I'm wondering is why have I never seen this technique before? I've never once seen anyone try to inherit from an unknown class using templates like this:
template <class T>
class Name : public T {
// Implementation
};
Is there a name to this technique, and what are it's uses?
I just gave it a try because knowing the rules of C++ I didn't see a reason why it wouldn't work. Since I can't seem to find a name for it anywhere I'm going to call this technique "Hyper Polymorphism" :)
Dynamic polymorphism happens at run time and static polymorphism at compile time. Dynamic polymorphism requires typically a pointer indirection at run time (read the post "Demystifying virtual functions, Vtable, and VPTR in C++"), but static polymorphism has no performance costs at run time.
Definition. Static polymorphism is a type of polymorphism that collects the information to call a method during compile time while dynamic polymorphism is a type of polymorphism that collects information to call a method at run time. Thus, this is the main difference between static and dynamic polymorphism.
Dynamic polymorphism is a process or mechanism in which a call to an overridden method is to resolve at runtime rather than compile-time. It is also known as runtime polymorphism or dynamic method dispatch. We can achieve dynamic polymorphism by using the method overriding.
Dynamic Polymorphism allows Java to support overriding of methods which is central for run-time polymorphism. It allows a class to specify methods that will be common to all of its derivatives while allowing subclasses to define the specific implementation of some or all of those methods.
EDIT: sorry misunderstood an important part of OPs code. Shame on me. Removed the wrong part of my answer. However, the following still holds...
Imho your comparison isnt fair
Base* c2 = new Class2;
//cout << c2->y << endl; // Doesn't work! Not visible from here
ClassX<Class1> cx1;
cout << cx1.x << endl; // The member variable is visible!
These are two completely different cases. A fair comparison would be
Base* c2 = new Class2;
//cout << c2->y << endl; // Doesn't work! Not visible from here
vs
Base* cx1 = new ClassX<Class1>();
//cout << cx1->x << endl; // Wont work as well !!!
(see here for an example) or
Class2 c2;
cout << c2.y << endl; // Works of course
vs
ClassX<Class1> cx1;
cout << cx1.x << endl; // Works of course as well !!!
That said, this technique might have its applications. For example the case you mentioned in a comment, when you need to add the same functionality to many differnt base classes.
Is there a name to this technique, and what are it's uses?
Afaik there isnt a name for this. The uses are, as others have mentioned in comments, to decorate many different classes with the same functionality.
I have to admit that only after @Amadeus pointed out that half of my answer was wrong, I fully understood the approach in OPs code. Imho it is quite some effort (twice inheriting plus a template) for not too much gain, and maybe thats the reason why it isnt a well known and commonly applied technique. Though it might be useful in some special cases.
From reading the comments it looks like this technique is actually considered a "decorator pattern".
It can be used when you need to extend the functionality of multiple existing classes (for example adding a member variable z
) when you can't modify the classes directly.
It's more flexible than regular inheritance because you can extend the functionality of many classes by only writing one new class.
Not exactly the same as "hyper polymorphism", but hey, maybe that will be a thing some day. ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With