天天看點

C++實作字元串建立類

原理 利用 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");
    //結束
}
           

繼續閱讀