练习19.9
编写与本节最后一个程序类似的代码,令其打印你的编译器为一些常见类型所起的名字。
如果你得到的输出与本书类似,尝试编写一个函数将这些字符串翻译成人们更容易理解的形式。
解答:
<pre name="code" class="cpp">#include <iostream>
#include <typeinfo>
#include <vector>
#include <list>
#include <string>
#include <map>
#include <regex>
using namespace std;
string type_map(const string& str){
string res_str;
if(str.size() == 1){
switch(str.at(0)){
case 'c': res_str = "char"; break;
case 'h': res_str = "unsigned char"; break;
case 's': res_str = "short"; break;
case 't': res_str = "unsigned short"; break;
case 'i': res_str = "int"; break;
case 'j': res_str = "unsigned int"; break;
case 'l': res_str = "long"; break;
case 'f': res_str = "float"; break;
case 'd': res_str = "double"; break;
case 'm': res_str = "size_t"; break;
case 'x': res_str = "long long"; break;
case 'y': res_str = "unsigned long long"; break;
case 'e': res_str = "long double"; break;
}
} else {
return string();
}
return res_str;
}
void parse(const char* cstr){
size_t ch_num;
string str(cstr), res_str, patten("");
smatch res, res_2;
regex r1("([APSt]*)?([0-9]*)?([_]*)?([P]*)?([0-9]*)?([A-Za-z0-9_]*)?");
regex_search(str, res, r1);
if (!res[2].str().empty()){
ch_num = atoi(res[2].str().c_str());
patten = "([A-Za-z0-9_]{" + res[2].str() + "})(I)?([a-z])?";
}
regex r2(patten);
if (res.str().size() == 1){
res_str += type_map(res.str());
} else if (res[1].str() == "A" && ch_num != 0){
if(res[4].str() == "P"){
res_str += "*";
} else if(res[4].str() == "PP"){
res_str += "**";
}
if (res[6].str().size() == 1){
res_str += type_map(res[6].str());
} else {
res_str += res[6].str();
}
res_str += "[" + res[2].str() + "]";
} else if (res[1].str() == "P"){
res_str += "*";
if (res[6].str().size() == 1){
res_str += type_map(res[6].str());
} else {
regex_search(res[6].str(), res_2, r2);
res_str += res_2.str();
}
} else if (res[1].str() == "PP"){
res_str += "**";
regex_search(res[6].str(), res_2, r2);
if (res[6].str().size() == 1){
res_str += type_map(res[6].str());
} else {
regex_search(res[6].str(), res_2, r2);
res_str += res_2.str();
}
} else if (res[1].str() == "S"){
res_str += "std::";
if (res[6].str() == "s"){
res_str += "string";
}
} else if (res[1].str() == "St"){
res_str += "STL ";
regex_search(res[6].str(), res_2, r2);
res_str += res_2[1].str();
res_str += "<";
res_str += type_map(res_2[3].str());
res_str += ">";
} else{
regex_search(res[6].str(), res_2, r2);
res_str += res_2.str();
}
// TODO map type
cout << "this object type is " << res_str << "." << endl;
}
#ifdef WIN32
#define parse(a) cout << (a) << endl
#endif
class Base{};
int main(){
int inum;
int *pa;
int **ppa;
long long larr[10];
Base *pb;
Base **ppb;
Base barr[100];
Base base;
vector<float> iv;
list<float> fl;
parse(typeid(inum).name());
parse(typeid(pa).name());
parse(typeid(ppa).name());
parse(typeid(larr).name());
parse(typeid(pb).name());
parse(typeid(ppb).name());
parse(typeid(barr).name());
parse(typeid(base).name());
parse(typeid(iv).name());
parse(typeid(fl).name());
}
我这里实现的也不简单…… 自己都感觉很复杂,各种判断……
本来以为可以一个函数搞定的,写到后面才发现这个分析也不是很简单。
本来还要加pair和map的,看了一下输出字符…… 放弃了。
如果觉得有必要,可以用自定义类进行分析。(做过视频处理程序的朋友可能能理解为什么这样做)
在linux下,clang和gcc的输出和书上的一致。(我当前工作的环境也是linux)
当然,也在VS2013中试过,VS更加的友好,显示出来的类能直接进行判别。
相同代码,使用cout将typeid().name()打印出来的结果:(代码也做了相应的修改)
int
int *
int * *
__int64 [10]
class Base *
class Base * *
class Base [100]
class Base
class std::vector<float,class std::allocator<float> >
class std::list<float,class std::allocator<float> >
练习19.10
已知存在如下的类继承体系,其中每个类定义了一个默认公有的构造函数和一个虚析构函数。下面的语句将打印哪些类型名字?
class A{/* ... */};
class B : public A {/*...*/
class C : public B {/*...*/};
(a) A *pa = new C;
cout << typeid(pa).name() << endl;
(b) C cobj;
A& ra = cobj;
cout << typeid(&ra).name() << endl;
(c) B *px = new B;
A& ra = *px;
cout << typeid(ra).name() << endl;
解答:
(a) P1A
(b) P1A
(c) 1B (注意这里是对指针的引用)
#include <iostream>
#include <typeinfo>
using namespace std;
class A{
public:
A() = default;
virtual ~A(){}
};
class B : public A {
public:
B() = default;
virtual ~B(){};
};
class C : public B {
public:
C() = default;
virtual ~C(){};
};
#define choose 2
int main(){
#if choose == 1
A *pa = new C;
cout << typeid(pa).name() << endl;
#elif choose == 2
C cobj;
A& ra = cobj;
cout << typeid(&ra).name() << endl;
#else
B *px = new B;
A& ra = *px;
cout << typeid(ra).name() << endl;
#endif
}