C++爱好者在和python、php粉丝骂战时,经常会碰到一个难题“你们c++不支持动态数据类型,会大幅降低开发效率”
C++的语法要求在编译时确定变量的类型,属于静态数据类型语言。
静态数据类型的好处是在编程时一旦类型出错(例如对int变量写入string值),会在编译时报错。一旦编译通过,基本就不会存在类型错误的bug了。对于数万行的大型软件,在核心部分采用静态数据类型会更易于维护。
而支持动态数据类型的语言可以在运行时随意更改变量类型。
在实现多层map、制作可变参数通用api等几种情况下,动态数据类型可以大幅提高开发效率。
让我们来看一个小例子:
假如我们要在lua里写一个三层table,大概是这样:
- data = {}
- data["key1"] = {}
- data["key1"]["key2"] = {}
- data["key1"]["key2"]["key3"] = "邓小超"
- if data["key1"] ~= nil and data["key1"]["key2"] ~= nil then
- print(data["key1"]["key2"]["key3"])
- end
假如我们要在c++里干这件事,大概是:
- map<string, map<string, map<string, string> > > data;
- map<string, map<string, map<string, string> > >::iterator it_1 = data.find("key1");
- if(it_1 != data.end())
- {
- map<string, map<string, string> >::iterator it_2 = it_1->second.find("key2");
- if(it_2 != it_1->second.end())
- {
- map<string, string>::iterator it_3 = it_2->second.find("key3");
- if(it_3 != it_2->second.end())
- printf("%s\n", it_3->second.c_str());
- }
- }
光看看就觉得郁闷。
这还仅仅是最简单的情况,如果在key1下还有key2_1,key2_2....... 基本上只能跑去定义一堆struct了
噢,杀了我吧,太他妈复杂了。
通过引入jsoncpp库,我们可以这样做:
-
try
-
{
-
Json::Value data;
-
data["key1"]["key2"]["key3"] = "邓小超";
-
printf("%s\n", data["key1"]["key2"]["key3"].asCString());
-
}
-
catch(...)
-
{
-
printf("some data missed\n");
- }
C++居然能使用动态数据类型了!!!这不科学!!!
C++的语法虽然要求我们在编译时确定数据类型。但是我们可以用指针指向任意类型的数据,从而避开编译时的检查。例如多态就是利用了虚指针来支持运行时调用不同的子类成员函数。
更进一步,可以通过指针加类型让c++支持动态数据类型。
- class auto_type
-
{
-
void *point;
-
int type;
-
public:
-
//各种函数,通过type判断类型,然后处理point指向的数据
- }
jsoncpp库利用类似的原理,让我们可以在运行时动态的指定数据类型,相当于让C++支持了动态数据类型。
性能上jsoncpp会比直接使用int、string、map、vector要低,但是比起脚本语言还是要高上数倍。