c++動態創建對象,思路:按照對象名稱來動態創建,將對象名稱與創建函數一起保存到map中,創建時通過map來查找返回;
#pragma once
#include "DynCreateBase.h"
#include <iostream>
using namespace std;
class Shape
{
public:
Shape() = default;
virtual void Draw() = 0;
~Shape() {}
};
class Rect :public Shape
{
public:
Rect() :Shape() {}
~Rect() {}
virtual void Draw() override
{
std::cout << " Draw Rect" << std::endl;
}
};
class Circle :public Shape
{
public:
Circle() :Shape() {}
~Circle() {}
virtual void Draw() override
{
std::cout << "Draw Circle" << std::endl;
}
};
class Triangle :public Shape
{
public:
Triangle() :Shape() {}
~Triangle() {}
virtual void Draw() override
{
std::cout << "Draw Triangle" << std::endl;
}
};
REGISTER_OBJ(Rect); //只需要通過宏來註冊創建函數即可
REGISTER_OBJ(Circle);
REGISTER_OBJ(Triangle);
//動態創建類的實現,需要兩個接口,create與register,靜態成員變量 map,代碼如下
#pragma once
#include <map>
#include <functional>
typedef void *(*CreateFunc)();
class DynCreateBase
{
public:
DynCreateBase() =default;
~DynCreateBase() =default;
static void* DynamicCreate(const std::string &strName)
{
auto it = m_createMap.find(strName);
if (it != m_createMap.end())
{
return (void*)(it->second());
}
return nullptr;
}
static void RegisterCreate(const std::string &strName, CreateFunc func)
{
m_createMap[strName] = func;
}
private:
static std::map<std::string, CreateFunc> m_createMap;
};
按照上面REGISTER_OBJ(Rect)宏完成自動註冊的功能,
class Register
{
public:
Register(const std::string &str, CreateFunc func)
{
DynCreateBase::RegisterCreate(str, func);
}
};
#define REGISTER_OBJ(class_name) \
class class_name##Register { \
public: \
static void *newInstatnce() \
{ \
return new class_name;\
} \
private: \
static Register m_reg; \
}; \
__declspec(selectany) Register class_name##Register::m_reg(#class_name, &class_name##Register::newInstatnce);
核心技巧爲在宏中通過static Register m_reg; 來自動完成註冊,通過static 自動構造函數過程中,傳遞name與註冊函數來達到自動註冊的目的
完成代碼 shape.h
#pragma once
#include "DynCreateBase.h"
#include <iostream>
using namespace std;
class Shape
{
public:
Shape() = default;
virtual void Draw() = 0;
~Shape() {}
};
class Rect :public Shape
{
public:
Rect() :Shape() {}
~Rect() {}
virtual void Draw() override
{
std::cout << " Draw Rect" << std::endl;
}
};
class Circle :public Shape
{
public:
Circle() :Shape() {}
~Circle() {}
virtual void Draw() override
{
std::cout << "Draw Circle" << std::endl;
}
};
class Triangle :public Shape
{
public:
Triangle() :Shape() {}
~Triangle() {}
virtual void Draw() override
{
std::cout << "Draw Triangle" << std::endl;
}
};
REGISTER_OBJ(Rect);
REGISTER_OBJ(Circle);
REGISTER_OBJ(Triangle);
DynCreateBase.h自動構造與註冊定義類
#pragma once
#include <map>
#include <functional>
typedef void *(*CreateFunc)();
class DynCreateBase
{
public:
DynCreateBase() =default;
~DynCreateBase() =default;
static void* DynamicCreate(const std::string &strName)
{
auto it = m_createMap.find(strName);
if (it != m_createMap.end())
{
return (void*)(it->second());
}
return nullptr;
}
static void RegisterCreate(const std::string &strName, CreateFunc func)
{
m_createMap[strName] = func;
}
private:
static std::map<std::string, CreateFunc> m_createMap;
};
__declspec(selectany) std::map<std::string, CreateFunc> DynCreateBase::m_createMap;
class Register
{
public:
Register(const std::string &str, CreateFunc func)
{
DynCreateBase::RegisterCreate(str, func);
}
};
#define REGISTER_OBJ(class_name) \
class class_name##Register { \
public: \
static void *newInstatnce() \
{ \
return new class_name;\
} \
private: \
static Register m_reg; \
}; \
__declspec(selectany) Register class_name##Register::m_reg(#class_name, &class_name##Register::newInstatnce);
測試代碼
#include <iostream>
#include <vector>
#include "shape.h"
#include "DynCreateBase.h"
int main()
{
std::vector<Shape* >vec;
vec.push_back((Shape*)DynCreateBase::DynamicCreate("Rect"));
for (auto var:vec)
{
var->Draw();
}
system("pause");
return 0;
}