Reputation: 349
Is it possible to do multiple definition of same class function (polymorphism) depending on multiple type of inherited class:
#include <iostream>
#include <vector>
#include <string.h>
//All base A class
class A{
public:
int e = 0;
virtual int GetE() = 0; //to make A virtual
};
class A_A : public A{
public:
A_A(){e=1;}
virtual int GetE(){return e;}
};
class A_B : public A{
public:
A_B(){e=2;}
virtual int GetE(){return e;}
};
//All base B Class
class B{
public:
virtual void ActionOnA(A_A& a){a.e = 100;}
virtual void ActionOnA(A_B& a){a.e = 200;}
virtual void ActionOnA(A& a){}
};
class B_A : public B{
public:
/*
B_A as the same behavior of B class but B is virtual
*/
};
class B_B : public B{
public:
/*
B_B do different things on A depending on which A object is passed
*/
virtual void ActionOnA(A_A& a){a.e += -100;}
virtual void ActionOnA(A_B& a){a.e += -200;}
virtual void ActionOnA(A& a){}
};
//now I create a custom A_* class
class A_C : public A{
public:
A_C(){e=90;}
virtual int GetE(){return e;}
};
//Since A_C is never handled anywhere, I must create a new B_* to handle it
//I want it have the behavior of B_A in every A class except for A_C
class B_C : public B_A{
public:
virtual void ActionOnA(A_C& a){a.e = 0;}
};
int main(int argc, const char *argv[])
{
std::vector<A*> AllMyA;
A_A Object1;
A_B Object2;
A_C Object3;
AllMyA.push_back(&Object1);
AllMyA.push_back(&Object2);
AllMyA.push_back(&Object3);
B_A test;
for(A* a : AllMyA){
test.ActionOnA(*a);
std::cout << a->GetE() << '\n';
}
/*
Result should be :
100
200
90
Result is :
1
2
90
*/
AllMyA.clear();
A_A Object4;
A_B Object5;
A_C Object6;
AllMyA.push_back(&Object4);
AllMyA.push_back(&Object5);
AllMyA.push_back(&Object6);
B_B test2;
for(A* a : AllMyA){
test2.ActionOnA(*a);
std::cout << a->GetE() << '\n';
}
/*
Result should be :
100
200
0
Result is :
1
2
90
*/
}
This example don't work, it always call ActionOnA(A& a). Can someone explain me how could I make it work knowing the fact I can't do static_cast because I don't know which type of A_* my A ptr is? Isn't exist a better way of working? Maybe with template?
Upvotes: 1
Views: 61
Reputation: 1110
There is a big difference between the functions ActionOnA
and GetE
; GetE
is a virtual function, thus, the compiler writes down a jump to the corresponding function in the object's virtual function table, which is determined in run-time.
However, when we look at ActionOnA, the compiler need to "know" what function to write down on compile time (it is not virtual!), therefore, it puts the most suitable function overload, which is ActionOnA(A*)
. The same problem will occur with templates, which are determined at compile time, therefore, it won't choose the overload according to its run-time type.
As ChrisMM wrote, you can try to make dynamic_cast
that may fail. But it seems to me that the problem is a bit different:
You want to have a dynamic function in A which makes the valid operation on run-time:
virtual void updateE(bool shouldResetE);
In A_A:
void updateE(bool shouldResetE) final
{
this->E = shouldResetE ? 100 : this->E - 100;
}
Also, a strong recommendation is to use both override
and final
specifiers, since it helps catching errors in compile time (override
will warn when not properly overriding a function, final
will warn when trying to override this function on inheriting classes). If A_* are not meant to be inherited from, specify it using final
.
Upvotes: 1