C++ 的显式转换static_cast和dynamic_cast (下

1.dynamic_cast的使用

dynamic_cast主要是针对多态场景(虚函数)。运行时会进行类型检查,所以dynamic_cast判断一下 转换是否成功,再进行下一步操作。

2.实际上代码理解

//基础控件类
class UiElement{
public:
        virtual void handle_msg(string &msg) = 0;  //消息改成引用模式
        virtual ~UiElement(){}
};

//具体文本类
class TextElement : public UiElement{
public:
    void handle_msg(string &msg)
    {
        if("text" == msg)
        {
            cout<<"Handle text !"<<endl;
            text = msg; //重载operator=  , 构造是重新分配了空间
        }

    }

    //文件类的其它普通方法,例如:显示text
    void show_text()
    {
        cout<<"simulator_show_text: "<<text<<endl;
    }

private:
    string text;
};

//具体的button类
class ButtonElement: public UiElement{
public:
    void handle_msg(string &msg) override
    {
        if("button" ==  msg)
        {
            cout<<"Handle button message!"<<endl;
            button_event = msg;
        }
    }

    //定义了自己的方法
    void process_click()
    {
        if(button_event == "button"){
            cout<<"Button is click!! "<<endl;
        }
    }
private:
    string button_event;
};

class EventDispatch{
public:
    void dispatch_msg(UiElement * element,  string &msg)    //处理,主要针对一个消费者(要使用基类,派生了多种),一个消费产品(其实产品也可以衍生)
    {
        element->handle_msg(msg);


        //获取到的基类指针,先试用dynamic_cast进行显式转换(要转换的,必须要含有虚函数),判断,是不是自己这个派生类需要处理的内容!
        TextElement *_text_obj = dynamic_cast<TextElement *>(element);  //必须要显式转换,向下转换,需要用户关系安全问题
        if("text" == msg && _text_obj ){    //安全转换要注意,判断一下是否转换成功
            _text_obj->show_text();
        }

        //通过基类指针进行dynamic_cast 显式转换(向下转型,注意安全)
        ButtonElement *_button_obj = dynamic_cast<ButtonElement *> (element);
        if("button" == msg && _button_obj ){
            _button_obj->process_click();
        }
    }
};

void test_dispatch_msg()
{
    string text_msg("text");
    string button_msg("button");
    EventDispatch  _event_dispatch_obj;

    //----测试文本控件使用
    unique_ptr<TextElement> _text_obj = unique_ptr<TextElement>(new TextElement());
    _event_dispatch_obj.dispatch_msg(_text_obj.get(),   text_msg);  //安全转换成text

    //---测试按钮控件使用
    unique_ptr<ButtonElement> _button_obj = unique_ptr<ButtonElement>(new ButtonElement());
    _event_dispatch_obj.dispatch_msg(_button_obj.get(),  button_msg);   //安全转换成button

    UiElement * _button_ptr = new ButtonElement();
    TextElement *_text_ptr = dynamic_cast<TextElement *>(_button_ptr); //使用安全转换,但是这里,是成功不了的!!(本质是button对象)
    if(!_text_ptr)
    {
        cout<<"Failed to translate button obj to text obj! "<<endl; //可以有效防止,类型转换导致错误使用,派生类方法
    }



}

上面代码中基类(不实例化),基类派生类对象2个,还有一个处理消息分发的类, 这个类里面,负责分发消息,并通过类型的显式转换判断(dynamic_cast运行时,会检查类型), 然后判断是否转换成功,在进行操作。 处理结果:

Handle text !
simulator_show_text: text
Handle button message!
Button is click!!
Failed to translate button obj to text obj!
-------end-------