zoukankan      html  css  js  c++  java
  • [C++学习笔记14]动态创建对象(定义静态方法实现在map查找具体类名对应的创建函数,并返回函数指针,map真是一个万能类)good

    [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__
      复制代码
      
      复制代码
      #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__
      复制代码
      
      复制代码
      #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;
      }
      复制代码
      
      复制代码
      #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)
       

    http://www.cnblogs.com/ifpelset/articles/4544750.html

  • 相关阅读:
    关于在php+apache开发过程中使用svn进行版本的维护
    Fragment的切换动画实现
    IOS MJExtension json转模型的轻量级框架的使用
    Centos 配置Red5流媒体服务器
    在Centos 6.5 上面配置 SVN
    在Centos 上面配置Openfire
    关于阿里云上面的Centos上面配置 防火墙
    【Android 一些难以理解的控件、容易混淆的、多种实现方式的、一些该纠正的想法】
    【进攻移动开发_htm5_跨平台_的号角】
    【进攻Android的号角】
  • 原文地址:https://www.cnblogs.com/findumars/p/7968652.html
Copyright © 2011-2022 走看看