原理 利用 std::map存儲建構建構類的功能對象,通過字元串查找後實作運作時建立字元串對象
優點,減少判斷語句,可以通過維護一個字元串即可建立對象。不用寫一串switch case語句。
擴充好,可以建立多個派生類對象而無需再次維護生成對象的工廠類。
直接上代碼:main函數裡面:
int main()
{
/*
* _CIN : 聲明類可以通過字元串建立
* _CNEW : 通過字元串建立類
*/
//聲明該類的可被字元串建立
_CIN(B)
_CIN(A)
_CIN(Item)
//使用:
cout << "還沒有建立對象" << endl;
auto aClass = (Base*)_CNEW("A"); //生成類
aClass->print(); //通過接口調用
//當發生錯誤:
auto NULL_Class = (Base*)_CNEW("S"); //S這個類沒有被聲明到可以通過類名建立
system("pause");
//結束
}
聲明可以被建立的對象,然後直接通過字元串調用得到該對象的對象指針
還沒有建立對象
A被建立
10
Class name not "CIN" to the initialization list
These classes can be created :
[A,B,Item,]
請按任意鍵繼續. . .
可以看見 是在get函數時才建立對象
這裡主要運用了map ,抽象類 還有宏技術
原理很簡單 用一個單例去管理類的工廠類,聲明的本質就是建立工廠類和往建立功能類裡面添加工廠
其實也可以通過繼承建立類去實作傳回即用,重寫傳回函數就可以了。但是這是具體需求,就有在建立吧。
直接上源碼 單頭檔案即可運作
#ifndef _STR_NEW_CLASS
#define _STR_NEW_CLASS
#include <iostream>
#include <map>
#include <string>
namespace __CC{
class _CBase
{
public:
virtual void* getClass() = 0;
};
#define _CC(A)\
class _CBase##A : public __CC::_CBase\
{\
public:\
void* getClass()override {\
return new A();\
}\
};
class _Create
{
public:
static _Create& instance();
void* get(const std::string& str);
std::map<std::string, _CBase*> data;
private:
_Create() {}
};
//use
#define _CIN(A) _CC(A) __CC::_Create::instance().data[#A] = new _CBase##A;
#define _CNEW(str) __CC::_Create::instance().get(str)
//end
//實作
void* _Create::get(const std::string& str)
{
if (data.find(str) != data.end()) {
return data[str]->getClass();
}
std::cout << "Class name not \"CIN\" to the initialization list" << std::endl;
std::cout << " These classes can be created : " << std::endl;
std::cout << "[";
for (auto item : data) {
std::cout << item.first << ",";
}
std::cout << "]"<<std::endl;
return nullptr;
}
_Create& _Create::instance()
{
static _Create* ins = nullptr;
if (ins == nullptr) {
ins = new _Create;
}
return *ins;
}
}
#endif // !_STR_NEW_CLASS
主函數完整代碼
// 字元串構造類.cpp : 此檔案包含 "main" 函數。程式執行将在此處開始并結束。
//
#include <iostream>
#include <string>
#include <map>
#include "strNewClass.h"
using namespace std;
//一個普通的基類()其實應該叫接口
class Base {
public:
virtual void print() = 0;
};
//一個普通的實作
class A :public Base
{
public:
void print()override{cout << this->a << endl;}
A(const int& i) { a = i; }
A() { cout << "A被建立"<<endl; }
int a = 10;
};
//又一個普通的實作
class B : public Base
{
public:
void print()override{cout << this->a << endl;}
B(const float& i){ a = i; }
B() { cout << "B被建立"<<endl; }
float a = 20;
};
//更加普通的實作,就一個接口
class Item : public Base
{
public:
void print()override
{
cout << "我不知都呀" << endl;
}
};
int main()
{ /*
* 使用說明:
* 使用對象共兩個: _CIN _CNEW
* _CIN : 聲明類可以通過字元串建立
* _CIN(參數) 參數:為類的名稱 (非字元串)
*
* _CNEW : 通過字元串建立類
* 傳回值 _CNEW(參數) 傳回值為(void*)的對象。參數為字元串("className")
* 具體使用案例如下
*/
//聲明該類的可被字元串建立
_CIN(B)
_CIN(A)
_CIN(Item)
//由于比較底層 是以加了一個_ 下劃線
//使用:
cout << "還沒有建立對象" << endl;
auto aClass = (Base*)_CNEW("A"); //生成類
aClass->print(); //通過接口調用
//當發生錯誤:
auto NULL_Class = (Base*)_CNEW("S"); //S這個類沒有被聲明到可以通過類名建立
system("pause");
//結束
}