[C++学习笔记14]动态创建对象

  1. C#/Java中的反射机制
      动态获取类型信息(方法与属性)
        动态创建对象
        动态调用对象的方法
        动态操作对象的属性
      前提:需要给每个类添加元数据

  2. 动态创建对象
      实现原理:通过定义一个宏REGISTER_CLASS,传入类名,在该宏中创建一个类独有的Register类,类中定义静态方法创建对象(new)并返回指针,并在该类中定义一个公共Register类的成员变量,在该公共Register类的构造函数调用工厂类的Register方法注册类名与创建对象的函数指针到map,在工厂类中定义静态方法实现在map查找具体类名对应的创建函数,并返回调用即可。
      具体实现代码
    #ifndef __DYN_BASE_H__
    #define __DYN_BASE_H__
    
    #include <map>
    #include <string>
    using namespace std;
    
    typedef void* (*CREATE_FUNC)();
    
    class DynObjectFactory {
    public:
        static void *createObject(const string &name)
        {
            map<string, CREATE_FUNC>::const_iterator it;
            it = mapCls_.find(name);
    
            if (it == mapCls_.end())
                return nullptr;
            
            return it->second();
        }
    
        static void Register(const string &name, CREATE_FUNC func)
        {
            mapCls_[name] = func;
        }
    
    private:
        static map<string, CREATE_FUNC> mapCls_;
    };
    
    // g++
    // __attribute ((weak))
    __declspec(selectany) map<string, CREATE_FUNC> DynObjectFactory::mapCls_;
    
    class Register {
    public:
        Register(const string &name, CREATE_FUNC func)
        {
            DynObjectFactory::Register(name, func);
        }
    };
    
    #define REGISTER_CLASS(class_name) \
    class class_name##Register{ \
    public: \
        static void* newInstance() \
    { \
        return new class_name; \
    } \
    private: \
        static Register reg_; \
    }; \
    Register class_name##Register::reg_(#class_name, class_name##Register::newInstance);
    
    #endif // __DYN_BASE_H__
    DynBase.h
    #ifndef __SHAPE_H__
    #define __SHAPE_H__
    
    #include <iostream>
    #include <vector>
    #include <string>
    using namespace std;
    
    class Shape {
    public:
        virtual void Draw() = 0;
        virtual ~Shape() {}
    };
    
    class Circle : public Shape {
    public:
        void Draw();
        ~Circle();
    };
    
    class Rectangle : public Shape {
    public:
        void Draw();
        ~Rectangle();
    };
    
    class Square : public Shape {
    public:
        void Draw();
        ~Square();
    };
    
    #endif // __SHAPE_H__
    Shape.h
    #include "Shape.h"
    #include "DynBase.h"
    
    void drawAllShapes(const vector<Shape *> v)
    {
        vector<Shape *>::const_iterator it;
        for (it = v.begin(); it != v.end(); ++it) {
            (*it)->Draw();
        }
    }
    
    void deleteAllShapes(const vector<Shape *> v)
    {
        vector<Shape *>::const_iterator it;
        for (it = v.begin(); it != v.end(); ++it) {
            delete (*it);
        }
    }
    
    int main(void)
    {
        //Shape s; // Error, 抽象类不能实例化对象
        vector<Shape *> v;
        Shape *ps = NULL;
    
        ps = static_cast<Shape *>(DynObjectFactory::createObject("Circle"));
        v.push_back(ps);
        ps = static_cast<Shape *>(DynObjectFactory::createObject("Square"));
        v.push_back(ps);
        ps = static_cast<Shape *>(DynObjectFactory::createObject("Rectangle"));
        v.push_back(ps);
    
        drawAllShapes(v);
        deleteAllShapes(v); // 未将Shape基类的析构函数声明为虚函数之前,并不会调用各个派生类的析构函数
        // 声明为虚函数之后,就会调用了
        return 0;
    }
    DynTest.cpp
    #include "Shape.h"
    #include "DynBase.h"
    
    void Circle::Draw() 
    {
        cout << "Circle Draw ... " << endl;
    }
    
    Circle::~Circle()
    {
        cout << "~Circle ... " << endl;
    }
    
    void Rectangle::Draw()
    {
        cout << "Rectangle Draw .." << endl;
    }
    
    Rectangle::~Rectangle()
    {
        cout << "~Rectangle ... " << endl;
    }
    
    void Square::Draw() 
    {
        cout << "Square Draw ..." << endl;
    }
    
    Square::~Square() 
    {
        cout << "~Square ... " << endl;
    }
    
    REGISTER_CLASS(Circle)
    REGISTER_CLASS(Square)
    REGISTER_CLASS(Rectangle)
    Shape.cpp

     


     

posted @ 2015-06-01 19:50  IFPELSET  阅读(269)  评论(0编辑  收藏  举报