I am still learning and I have a question I am hoping someone can help me with:
Is it possible to achieve compile time polymorphism of different classes inheriting from the same base class to be used in an array without using virtual functions?
As anyone that knows even a little OOP with C++ if you have something like
class Base {
public:
virtual void foo (){
std::cout << "I'm the base" << std::endl;
}
}
class A : public Base {
public:
void foo() {
std::cout << "I'm the child" << std::endl;
}
}
class B : public Base {
public:
void foo() {
std::cout << "I'm the child #2" << std::endl;
}
}
//Assume some main here
A *a = new A();
B *b = new B();
Base *someArray[] = {a,b};
someArray[0]->foo(); //"I'm the child"
someArray[1]->foo(); //"I'm the child #2"
We know this works because the functions are and inheritance is resolved run-time. However what I what to know is how to do this without virtual functions or if its possible to do this same thing without using virtual functions?
Suppose you do something like this
class Base {
public:
void foo (){
std::cout << "I'm the base" << std::endl;
}
}
class A : public Base {
public:
void foo() {
std::cout << "I'm the child" << std::endl;
}
}
class B : public Base {
public:
void foo() {
std::cout << "I'm the child #2" << std::endl;
}
}
//Assume some main here
A *a = new A();
B *b = new B();
Base *someArray[] = {a,b};
someArray[0]->foo(); //"I'm the base"
someArray[1]->foo(); //"I'm the base"
So there is a lot of options but I can't seem to find something that will have the same behavior that I want. One solution I read about is making a static class template that works something like this
template <class T>
class Base
{
public:
void interface()
{
// ...
static_cast<T*>(this)->implementation();
// ...
}
static void static_func()
{
// ...
T::static_sub_func();
// ...
}
};
class Derived : Base<Derived>
{
public:
void implementation() {
std::cout << "I am derived" << std::endl;
}
static void static_sub_func();
};
class AlsoDerived : Base<Derived>
{
public:
void implementation() {
std::cout << "I am also derived" << std::endl;
}
static void static_sub_func();
};
//Assume in some main
Derived div;
AlsoDerived alsoDiv;
Derived *someArray[] = { &div, &alsoDiv };//does not work not the same type
Base *someArray[] = { &div, &alsoDiv }; //does not work b/c its a template
The above is not the behavior I want. And then there is static casting which seem promising however I need to know what class its going to be at any given time which is not the behavior I want.
class Base {
public:
void foo (){
std::cout << "I'm the base" << std::endl;
}
}
class A : public Base {
public:
void foo() {
std::cout << "I'm the child" << std::endl;
}
}
class B : public Base {
public:
void foo() {
std::cout << "I'm the child #2" << std::endl;
}
}
//Assume some main here
A *a = new A();
A *b = new A();
B *c = new B();
Base *someArray[] = {a,b,c};
someArray[0]->foo(); //"I'm the base"
static_cast<A*>(someArray[1])->foo(); //"I'm the child"
static_cast<B*>(someArray[2])->foo(); //"I'm the child #2"
This is very close to what I want however my problem is for the static_cast to work I need to know what class it is I want to static case and its not the behavior I want.
What do you think? Is there a better way do what I want?
Thanks for reading and if there is any confusion as to what I am asking please let me know so I can clarify.
tuples instead of arrays. In any case, the type of your collection will have to encode the individual type of each element, and target function resolution will have to happen at compile-time, probably through an overloaded free function. Maybe replacing your hierarchy with avariant?