This post is a working example for this Question. However, there are some points that confuse me. That is why I am posting it as another question.
Basically, the problem is how to cast a base class to its subclasses. People have suggested using dynamic memory and new
ing a fresh instance of the subclass.
I cam up with the following solution, and now wonder how this works. I create an object of the base class (Employee). Set its Id. Then I cast its pointer to a pointer of the subclass and set more members.
// Example program
#include <iostream>
#include <string>
#include <list>
#include <algorithm>
using namespace std;
class Employee {
public:
int getId() { return id;}
void setId( int id) {this->id = id;}
protected:
int id;
};
class PartTimeEmployee : public Employee {
};
class FullTimeEmployee : public Employee {
public:
int getGrade() {return grade;}
void setGrade(int grade) {this->grade = grade;}
private:
int grade;
};
class Organization {
public:
void addEmployee(Employee* e) { empList.push_back(e); }
Employee* getEmployee(int id) {
for (std::list<Employee*>::iterator it=empList.begin(); it!=empList.end(); ++it) {
if((*it)->getId() == id) {return (*it);}
}
return NULL;
}
private:
std::list<Employee*> empList;
};
int main()
{
Employee e1;
e1.setId(5);
FullTimeEmployee *pFt1 = (FullTimeEmployee*) &e1;
pFt1->setGrade(1);
Organization org1;
org1.addEmployee(pFt1);
FullTimeEmployee* pFt2 = (FullTimeEmployee*) org1.getEmployee(5);
cout << pFt2->getId() << endl;
cout << pFt2->getGrade() << endl;
}
Why does it work? I see it as follows:
Employee: |--id--|... FullTimeEmployee: |--id--|--grade--|...
1- Is this what happens in the background? When I cast to the FullTimeemployee, C++ copies all pre-existing members of the Employee class plus giving you more space based on the size of the new type.
2- Is it safe to use this approach? Should I prefer dynamic memory allocation, e.g. FullTimeEmployee *pFT1 = new FullTimeEmployee();
over this? If yes why? why can't I just go with pointer casting?
UPDATE: What makes this example different from casting to void*
? You just play with memory addresses. What can go wrong as long as you know how much memory you need?