一个困惑的类层次设计根据:回调函数,避免向下类型转换,该如何处理

一个困惑的类层次设计根据:回调函数,避免向下类型转换
class Element
{
virtual void doSomething();
};

ElementTree
{
Element * getElementInTree() {return data[i];}
void setElementInTree(Element* e) { e->doSomething(); i++; data[i]=e;}
private:
Element * data[] ;
int i;
};

class RedElement:Element
{
void doSomething() {int a=0; a++; ... ... };
void redDoSomething();
}
main()
{
Element *e = new RedElement();
ElementTree tree;
tree.setElementInTree(e);
Element *eBack = tree.getElementInTree();
//以下为了调用RedElement中才有的方法,不得不向下转化
RedElement *redEBack = dynamic_cast<RedElement>(eBack);
redEBack.redDoSomething() ;
}

关于上面的例子的问题:
effective c++中39条讲最好不要沿着类继承关系向下转换,那么是不是向下转换应该尽量少用?在什么情况下可以使用?
以上的的例子怎样重新设计,避免向下转换?
讲出这样设计的根据是什么,是什么设计理念使你这样做?




------解决方案--------------------
可以把类拆为可变的不变的吧
然后可变的类随便添加虚函数,不变的部分保持。


class Element
{
public:
virtual void doSomething();
CAlter *m_pAlter;

};
clasa CAlter
{
public:
virtual void redDoSomething();
}

class CRedAlter:public CAlter
{
public:
void redDoSomething(){.....};
}



ElementTree
{
Element * getElementInTree() {return data[i];}
void setElementInTree(Element* e) { e->doSomething(); i++; data[i]=e;}
private:
Element * data[] ;
int i;
};

class RedElement:Element
{
void doSomething() {int a=0; a++; ... ... };
void redDoSomething();
}
main()
{
Element *e = new RedElement();
ElementTree tree;
CAlter *a= new CRedAlter;
e->m_pAlter=a;
tree.setElementInTree(e);
Element *eBack = tree.getElementInTree();
//以下为了调用RedElement中才有的方法,不得不向下转化
//RedElement *redEBack = dynamic_cast<RedElement>(eBack);
eBack->m_pAlter->redDoSomething();
//redEBack.redDoSomething() ;
}

------解决方案--------------------
只是说避免滥用而已。不安全的操作用多了当然容易出问题。很遗憾,这种问题现实生活中不是总能避免的。否则类似的代码就根本不会出现了。
------解决方案--------------------
我觉得 楼主 这时的向下转换,是合理的。
因为这情况,不是在一般处理中的特殊化。它不会引起歧义,也不会发生错误。(它仅仅是处理Red的情况。不包括其它的子类,没有使用ifelse之类的。)
不过。我觉得这样写会更好些。。
C/C++ code
class Element
{
virtual void doSomething();
};

ElementTree
{
enType{enRed,    enSize};
ElementTree(){m_data.resize(enSize);}
~ElementTree(){...delete..}
Element * getElementInTree(enType type) {return data[type];}
void setElementInTree(Element *&e,enType type) { e->doSomething(); m_data[type] = e;}
private:
std::vector<Element *> m_data;
};

class RedElement:Element
{
void doSomething() {int a=0; a++; ... ... };
void redDoSomething();
}
main()
{
Element *e = new RedElement();
ElementTree tree;
tree.setElementInTree(e,ElementTree::enRed);
Element *eBack = tree.getElementInTree(ElementTree::enRed);
//此段代码只是针对red。所以我觉得是合理的。若此段是被包含于对所有的Element的处理,就是不合理的。
RedElement *redEBack = dynamic_cast<RedElement>(eBack);
assert(redEBack);
redEBack.redDoSomething() ;
}