c/c++ 反射机制感悟

最近学习PISIP,代码很有层次感,其中的抽象层实现很值得学习

顺便又关心了一下工厂设计模式,加深了对该模式的理解,做了个笔记

感谢这篇文章https://blog.csdn.net/zhangqi_gsts/article/details/53395297,令我思路更清晰


引用其中的例子, 加上自己的理解:  


    class TestA:public Object  
    {  
    DECLARE_CLASS()  
    public:  
        TestA() {std::cout << "TestA constructor" << std::endl;}  
        ~TestA(){std::cout << "TestA destructor" << std::endl;}  
    };  
      
       IMPLEMENT_CLASS("testA_interface", TestA)  
      

    int main()    
    {    
       //1  所有可通过反射机制创建的类,具有相同的基类, 使用c++的“虚函数”机制,实现类实例化
      //   所以Object::CreateObject()并不是一定要返回Object指针,它可以返回任何一种(抽象)接口的指针
      //     这个就看编写代码时,具体对CreateObject函数的声明以及实现了
       //    本例中, 返回的接口什么也没做, 因为本例根本就没有实现任何的接口函数
     
        Object* obj = Object::CreateObject("testA_interface");  
        delete obj;  
        return 0;    
    }   

    //2 所有可通过反射机制创建的类,需要声明一个静态的类型信息成员, 该成员包含类名称和对应的类工厂函数指针
    //3 所有可通过反射机制创建的类,需要声明一个静态的工厂接口, 工厂接口返回一个接口指针
    //  本里中返回一个Object*实例, 因为Object未声明任何接口,所以返回的Object接口指针什么也做不了,只是在Object派生类实例化时,输出派生类的构造函数调用信息
    //  通过C++的多个基本继承,其实可以把接口声明从Object中抽离出来

    //  因为实现是雷同的,所以使用一个宏DECLARE_CLASS来简化派生声明代码编写
    #define DECLARE_CLASS() \  
        protected: \  1
            static ClassInfo ms_classinfo; \          
        public:  \  
            static Object* CreateObject();           

    //3 所有可通过反射机制创建的类,其构造函数应包含类名称和类实例的工厂接口 -- 因为工厂函数是static成员函数, 所以类实例化之前就可以使用    
    //  因为实现是雷同的,所以使用一个宏IMPLEMENT_CLASS来简化派生类实现代码编写                                
      
    #define IMPLEMENT_CLASS(interface_name, class_name) \  
        ClassInfo class_name::ms_classinfo(interface_name,(ObjectConstructorFn)class_name::CreateObject);\  
            Object* class_name::CreateObject() \  
                { return new class_name;}   

    //4     抽象工厂类可根据类名字符串,调用对应的类工厂函数,实现类实例的创建                       --- 注意下面的CreateObject
    //5     抽象类工厂需要一个注册函数来实现类名字符串与类工厂函数(属于该类的静态函数)的对应关系 -----注意下面的Register
    //      很明显,下面的Object申明中差一个“容器”,用来存储Register函数注册的类型信息
    //      当CreateObject被用来创建一个类实例时,需要查询“容器”中的类型信息, 根据类名称找到对应的类工厂函数来来创建对应的类实例

    class Object  
    {  
    public:    
        Object(){}  
    virtual ~Object(){}  
        static void Register(ClassInfo* ci);  
        static Object* CreateObject(const std::string &interface_name);  
    };


      MFC中有一个BEGIN_MESSAGE_MAP,它也是实现了不同消息ID与不同处理函数(指针)的映射,实现原理和这个类似。


      总结:
            其实通过反射机制创建类实例,就是抽象工厂类实现类实例的创建, 只不过在抽象工厂类的实现过程中
            通过一个叫做ClassInfo的中间类(接口)封装了各个类的类型信息(类名称 + 类工厂函数指针)
           这样抽象类工厂可以通过类名称(任何唯一标识类的ID均可)直接查询到类的类型信息,通过类型信息中包含的类工厂函数指针创建类实例

            抽象类工厂通过查找 类名称-类型信息映射表来定位类工厂函数指针,而不是通过在代码中使用使用一堆if语句或case语句进行硬编码实现,这样就可以通过配置文件来控制程序运行时使用那一种类实例来实现“业务”功能了。
            
           其实在C语言中也可以实现类似的机制, 最近学习PJSIP,在pjmedia编码器框架中,就就实现了相同的机制
           通过配置编码器名称,就可以在程序运行时, 根据SDP协商的编码器名称来创建对应的编码器实例

猜你喜欢

转载自blog.csdn.net/twd_1991/article/details/80689558
今日推荐