Assume there is a template class that is an abstract interface to keep track a series of data.
template<typename T> class SeriesData { virtual T valueAt(int i) const = 0; }; I decide to use vector to store the data so I inherits from it, I also add a function to add value to series.
template<typename T> class MySeriesData : public SeriesData<T> { T valueAt(int i) const {return values_[i];} void add(const T& value) {values_.push_back(value);} private: std::vector<T> values_; }; The class that is going to use the series of data.
template<typename T> class AT { public: T data() const {return data_;} void setData(SeriesData<T>* data) {delete data_; data_ = data;} private: SeriesData<T> *data_; }; class IT : public AT<int> { }; class ST : public AT<string> { }; There is also a class that implements some common logic:
class A { public: A(){} virtual ~A() {} protected: void common() {cout << "A common" << endl;} }; And there are two classes, each of which inherits from IT and ST, and both of which need to inherit from A. I want to have them inherit from A because there are so much common logic.
class Numbers : public A , public IT { }; class Strings : public A , public ST { }; In the main logic, I will use a pointer in type of A to dynamically create the instance of either Numbers or Strings based on the type client wants.
A* item; if(type == NUMBER) item = new Numbers(); else if(type == STRING) item = new Strings(); I can just use item to do those common things, which is good.
item->common(); However, for those logic that are related to AT. I would need to check the real type and then do cast.
item->common(); if(type == NUMBER) { IT* itemNumber = static_cast<Numbers*>(item); itemNumber->setData(new MySeries<int>()); } else if(type == STRING) { ST* itemString = static_cast<Strings*>(item); itemString->setData(new MySeries<string>()); } ..... if(type == NUMBER) { //Have to cast from A to the a type of AT first Numbers* itemNumber = static_cast<Numbers*>(item); //Another conversion MySeries<int>* numberValues = (MySeries<int>*)itemNumber->data(); numberValues->add(1); } else if(type == STRING) { Strings* itemString = static_cast<Strings*>(item); MySeries<string>* stringValues = (MySeries<string>*)itemString->data(); stringValues->add("1"); } This is annoying when the code is full of these if...else or switch...case, especially when there are more and more types.
Is it possible to cast the type more smartly? It will be nice if I can always (or in most of cases) use pointer of A to do all the stuffs.
item = static_cast<B*>(item)doesn't work like you think. Sinceitemis statically typed as anA*, assigning the casted pointer back toitemjust ends up giving you the same pointer that you started with. You need something more like this instead:if(type == NUMBER) { B *b = static_cast<B*>(item); b->get(); } else if(type == STRING) { C *c = static_cast<C*>(item); c->get(); }and so on.