【发布时间】:2011-04-03 14:08:21
【问题描述】:
可能重复:
CLASS macro in C++
您好,有没有什么方法可以用 __FUNCTION__ 之类的宏作为函数名来获取类名?我唯一的想法是用纯虚拟 toString 继承一些基类,并手动定义名称。谢谢。
【问题讨论】:
可能重复:
CLASS macro in C++
您好,有没有什么方法可以用 __FUNCTION__ 之类的宏作为函数名来获取类名?我唯一的想法是用纯虚拟 toString 继承一些基类,并手动定义名称。谢谢。
【问题讨论】:
这取决于上下文到底是什么。获得实现定义的类的内部名称的粗略等价物可能是使用 typeid 运算符,如图所示。请注意,输出是实现定义的。
typeid(yourclass).name()
【讨论】:
typeid 不是动态的。所以它不是正确的 RTTI,它只是返回一个 type_info 类型的静态全局对象。这对这个应用程序来说无关紧要,因为我们传递的是类型名,而不是对象:它永远是动态的。
最简单的方法可能是(定义一个宏)调用某个函数从__FUNCTION__(或__PRETTY_FUNCTION__ for GCC,或者甚至可能是__FILE__)派生类名。
【讨论】:
__FUNCTION__ 包含类名(就像 __PRETTY_FUNCTION__ 可能对 GCC 一样)。
使用宏定义类:
#define CLASS_WITH_NAME(name) name { const char * __NAME = #name;
class CLASS_WITH_NAME(class_name) // No "{" here!
丑陋的黑客,但我能想到的最好的。
【讨论】:
__NAME 是保留的。只需使用typeid(T).name() 并继续;您关心的任何实现都会产生不错的结果。
#define CLASS_WITH_NAME(name) namespace detail { class class_name_base_detail_##name { public: const char* _class_name_ = #name; }; protected: class_name_base_detail_##name(){} ~class_name_base_detail_##name(){} } class name , public detail::class_name_base_detail_##name 所以它的干扰是最小的。像CLASS_WITH_NAME(foo) { /* normal */ }; 或CLASS_WITH_NAME(bar) , public base, private mixin { /* normal */ }; 一样使用它,效果会更好。但不要实际使用它。
另一个替代方案可能如下,尽管它有自己的缺点
map<string, string> classdescrmap; // store association system name, development name
struct A{
A(){
classdescrmap[typeid(*this).name()] = "A";
}
};
struct B : A{
B(){
classdescrmap[typeid(*this).name()] = "B";
}
};
string getname(string const &key){
return classdescrmap[key];
}
int main(){
B b;
cout << getname(typeid(b).name());
}
【讨论】:
type_info 对象本身作为地图的键。 (我认为type_info 有一些机制恰好可以让std::less 处理它。)字符串不需要是唯一的,type_info 对象需要。此外,比较 type_info 对象可能比比较字符串更快。