• 动态创建对象


    回顾前面的文章,实现了一个简单工厂模式来创建不同类对象,但由于c++没有类似new "Circle"之类的语法,导致数中需要不断地ifelse地去判断,如果有多个不同类对象需要创建,显然这是很费神的,下面通过宏定义注册的方法来实现动态创建对象

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    #ifndef _SHAPE_H_
    #define _SHAPE_H_

    class Shape
    {
    public:
        virtual void Draw() = 0;
        virtual ~Shape() {}
    };

    class Circle : public Shape
    {
    public:
        void Draw();
        ~Circle();
    };

    class Square : public Shape
    {
    public:
        void Draw();
        ~Square();
    };

    class Rectangle : public Shape
    {
    public:
        void Draw();
        ~Rectangle();
    };

    #endif // _SHAPE_H_
     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    #include "Shape.h"
    #include "DynBase.h"
    #include <iostream>
    using namespace std;


    void Circle::Draw()
    {
        cout << "Circle::Draw() ..." << endl;
    }
    Circle::~Circle()
    {
        cout << "~Circle ..." << endl;
    }

    void Square::Draw()
    {
        cout << "Square::Draw() ..." << endl;
    }
    Square::~Square()
    {
        cout << "~Square ..." << endl;
    }

    void Rectangle::Draw()
    {
        cout << "Rectangle::Draw() ..." << endl;
    }

    Rectangle::~Rectangle()
    {
        cout << "~Rectangle ..." << endl;
    }

    REGISTER_CLASS(Circle);
    REGISTER_CLASS(Square);
    REGISTER_CLASS(Rectangle);

    DynBase.h:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
     
    #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 0;
            else
                return it->second(); //func();

        }

        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_;
    //头文件被包含多次,也只定义一次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)
    //CircleRegister

    #endif // _DYN_BASE_H_

    DynTest.cpp:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
    #include "Shape.h"
    #include "DynBase.h"
    #include <iostream>
    #include <vector>
    #include <string>
    using namespace std;



    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)
    {
        vector<Shape *> v;

        Shape *ps;
        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);


        return 0;
    }



    在DynBase.h 中#define了一个宏定义REGISTER_CLASS(class_name),且在Shape.cpp 中调用宏定义,拿REGISTER_CLASS(Circle);

    来说,程序编译预处理阶段会被替换成:
    class CircleRegister { 
    public: 

    static void* NewInstance() 

    return new Circle; 

    private: 

    static Register reg_; 

    }; 
    Register CircleRegister::reg_("Circle",CircleRegister::NewInstance);


    也即定义了一个新类,且由于含有static 成员,则在main函数执行前先执行初始化,调用Register类构造函数,在构造函数中调用

    DynObjectFactory::Register(name, func); 即调用DynObjectFactory 类的静态成员函数,在Register函数中通过map容器完成了

    字符串与函数指针配对的注册,如mapCls_[name] = func;


    进入main函数,调用DynObjectFactory::CreateObject("Circle") ,CreateObject函数中通过string找到对应的函数指针

    NewInstance),并且调用后返回创建的对象指针,需要注意的是 return it->second(); 中it->second 是函数指针,后面加括

    号表示调用这个函数。对宏定义中的#,##用法不熟悉的可以参考这里

    这样当需要创建多个不同类对象的时候,就不再需要写很多ifelse的判断了。


    参考:

    C++ primer 第四版
    Effective C++ 3rd
    C++编程规范

  • 相关阅读:
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
  • 原文地址:https://www.cnblogs.com/alantu2018/p/8471118.html
Copyright © 2020-2023  润新知