c++的動態類

特色源於變化,不變的東西,不靈活的東西,一般會失去光輝,技術也是,如果一個技術容易擴展,那麼它是一個好技術


今天介紹c++的動態類特性:

在介紹之前,先介紹c++11中的兩個關鍵字,auto和any,

(1)auto

auto可以表示任何類型,是c++11中的一個關鍵字符號,可以使得代碼簡潔,不用關心具體的類型,類型在編譯器編譯的時候決定:


如: auto a = 5;         // int

 auto b = 5.0f;    // float

 auto c = 5.0;     // double

 std::vector<int> name_list;

 auto iter = name_list.begin(); // 容器迭代器


 std::cout << a << b << c << endl;


         特別是容器迭代器,在沒有auto之前,我們只能不厭其煩的這樣定義:std::vector<int>::iterator it = name_list.begin()


(2) any

any 出現在boost中,也是c++11的特徵,與auto相比,any是一個類,有成員函數和屬性,只能通過any_cast<type>來獲得內部的值,而不能像auto一樣直接使用;

值得說明的是,any本身不是模板類,不像模板類一樣,定義的時候需要指明實例化類型,例如:any<int> a;(這樣定義是不對的,因爲any不是模板類),any只有賦值函數和構造函數是template的,所以可以像auto一樣使用, any i = 5;

any的出現讓C++彷彿變成了一種弱類型的動態語言。

動態語言:運行期間才做數據類型檢查的語言,即編譯的時候不知道每一個變量的類型

靜態語言:編譯期間做數據類型檢查的語言,即編譯的時候就知道每一個變量的類型,如C/C++、C#、JAVA
  強類型:變量一定是有類型的, 且變量/對象的類型一旦確定, 其類型不再允許更改,如C/C++/Java/C#
  弱類型: 變量的類型概念很弱或者沒有類型的概念, 不同變量的類型可以更改. 如php、Ruby


下面開始介紹c++的動態類特:


我們在編寫程序的時候,經常會出現需要擴展的情況,例如:
class CTest
{
public:
    CTest(){}
    ~CTest(){}


public:
    int m_a;
    int m_b;
};


如果理想的狀態下,這個類不需要添加新的變量,但是大多數時候,我們的程序需要進行修改和添加新的屬性。
例如我們需要給CTest類添加一個新的屬性, int m_c;  以前我一直是這樣添加的。 我也一直在尋找更好的方法。 上次看我同事的代碼,發現他很好的實現了這種添加。 他是在QT中使用
map<QString, QVariant>  m_propertys;
來保存屬性。我知道有很多高手會有更好的實現方法。不過這是我最見過最好的實現方式。


這裏我用boost的boost::any來實現。
#include <boost/any.hpp>
#include <iostream>
#include <string>
#include <map>


using std::string;
using std::map;
using boost::any_cast;






#define   AttrMap (boost::any_cast<map<int, int>>(propertys.property["C"]))


class CPropertys
{
public:
    CPropertys();
    ~CPropertys(){};


public:
    map <string, boost::any>  property; //這裏我沒有使用, m_property,
                                        //因爲這樣,訪問者看起來會更舒服些。
};


CPropertys::CPropertys()
{


    // ! 這個可以保存字符串變量
    property["A"] =  (string)"Hello";


    // ! 保存整數變量
    property["B"] =  (int)5;




    map<int, int>  a;
    a[1] = 7;
    // ! 保存map變量
    property["C"] =  (map<int, int>)a;
}






int main()
{
    CPropertys propertys;


    propertys.property["B"] = 99; 


    // ! 我們也可以使用函數來實現,查詢和設置,propertys中的map
    AttrMap[1] = 199;


    std::cout << boost::any_cast<int>(propertys.property["B"]) << std::endl;
    getchar();
    return 0;
}
















#include <boost/any.hpp>
#include <iostream>
#include <string>
#include <map>




using std::string;
using std::map;
using boost::any_cast;


#define AttrMap (boost::any_cast<map<int, int>>(propertys.property["C"]))


class CPropertys
{
public:
    CPropertys();
    ~CPropertys(){};


public:


    template <typename T> bool AddNewProperty(const string &stPropertyName, T &anyProperty);
    bool RemoveProperty(const string &stPropertyName);
    bool IsExistProperty(const string &stPropertyName);


    bool GetValue(const string &stPropertyName, boost::any &value);
    template <typename T> bool SetValue(const string &stPropertyName, T &anyProperty);


public:
    map <string, boost::any> property;
};












CPropertys::CPropertys()
{


    property["A"] = (string)"Hello";;
    property["B"] = (int)5;
    map<int, int> a;
    a[1] = 7;
    property["C"] = (map<int, int>)a;
}






template <typename T> bool 
CPropertys::AddNewProperty(const string &stPropertyName, T &anyProperty)
{
    if (IsExistProperty(stPropertyName))
    {
        return false;
    }
    else
    {
        property[stPropertyName] = anyProperty;
    }
    return true;
}






bool 
CPropertys::RemoveProperty(const string &stPropertyName)
{
    if (IsExistProperty(stPropertyName))
    {
        property.erase(stPropertyName);
        return true;
    }
    
    return false;
}




bool 
CPropertys::IsExistProperty(const string &stPropertyName)
{
    return (property.find(stPropertyName) != property.end());
}




bool 
CPropertys::GetValue(const string &stPropertyName, boost::any &value)
{
    if (IsExistProperty(stPropertyName))
    {
        value = property[stPropertyName];
    }


    return false;
}




template <typename T> bool 
CPropertys::SetValue(const string &stPropertyName, T &anyProperty)
{
    property[stPropertyName] = anyProperty;


    return true;
}






int main()
{
    CPropertys propertys;




    //propertys.property["C"]; 


    


    //map<int, int> &c = boost::any_cast<map<int, int>>(propertys.property["C"]);




    //c[1]






    




    AttrMap[10] = 199;


    propertys.property["B"] = 99; 


    std::cout << propertys.IsExistProperty("F") << std::endl;


    
    std::cout << propertys.property.size() << std::endl;


    //propertys.property["F"] = 999; //這句也是可以執行的,不過沒有用AddNewProperty函數來的專業




    int value = 323;
    propertys.AddNewProperty("F", value);


    std::cout << propertys.property.size() << std::endl;


    std::cout << boost::any_cast<int>(propertys.property["F"])<< std::endl;




    boost::any v;
    propertys.GetValue("F", v);
    std::cout << boost::any_cast<int>(v) << std::endl;
    value = 88888;
    propertys.SetValue("F", value);
    propertys.GetValue("F", v);
    std::cout << boost::any_cast<int>(v) << std::endl;




    std::cout << boost::any_cast<int>(propertys.property["B"]) << std::endl;
    getchar();
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章