【问题标题】:Class name macro [duplicate]类名宏[重复]
【发布时间】:2011-04-03 14:08:21
【问题描述】:

可能重复:
CLASS macro in C++

您好,有没有什么方法可以用 __FUNCTION__ 之类的宏作为函数名来获取类名?我唯一的想法是用纯虚拟 toString 继承一些基类,并手动定义名称。谢谢。

【问题讨论】:

标签: c++ class macros


【解决方案1】:

这取决于上下文到底是什么。获得实现定义的类的内部名称的粗略等价物可能是使用 typeid 运算符,如图所示。请注意,输出是实现定义的。

typeid(yourclass).name()

【讨论】:

  • +1,尽管 RTTI 仅被标准要求用于具有虚函数的类。
  • @Tony:嗯? §5.2.8/3:“当 typeid 应用于多态类类型的左值以外的表达式时,结果引用表示表达式静态类型的 type_info 对象。左值到右值 (4.1),数组- 到指针 (4.2) 和函数到指针 (4.3) 的转换不适用于表达式。”这涵盖了几个基础,特别排除了以虚函数为首要条件的类。
  • @Potatoswatter:令人着迷!我看到这是在标准草案中,它进入决赛了吗?许多其他参考资料(例如codingunit.com/…codeguru.com/cpp/tic/tic0270.shtmlen.wikipedia.org/wiki/Run-time_type_information)都非常明确地指出 RTTI 仅适用于动态类型,而且我确信多年来我已经在多个地方读到过这一点,尽管这可能早于C++03?任何知道的人 - 请加入....
  • @Tony:我认为他们的意思是非多态对象上的typeid 不是动态的。所以它不是正确的 RTTI,它只是返回一个 type_info 类型的静态全局对象。这对这个应用程序来说无关紧要,因为我们传递的是类型名,而不是对象:它永远是动态的。
【解决方案2】:

最简单的方法可能是(定义一个宏)调用某个函数从__FUNCTION__(或__PRETTY_FUNCTION__ for GCC,或者甚至可能是__FILE__)派生类名。

【讨论】:

  • +1 如果您将每个类放在不同的文件中,那么 FILE 是您最好的(交叉编译器)选项。
  • 是的,PRETTY_FUNCTION 包含 GCC 的类名,但我看不到更便携的 FUNCTION 的任何应用程序文件...?
  • @Aaron: 哦,哎呀...是的...哎呀... :-)
  • @Tony: 对于 Microsoft Visual Studio,__FUNCTION__ 包含类名(就像 __PRETTY_FUNCTION__ 可能对 GCC 一样)。
  • 哦,我明白了...感谢您的解释
【解决方案3】:

使用宏定义类:

#define CLASS_WITH_NAME(name)  name { const char * __NAME = #name;

class CLASS_WITH_NAME(class_name) // No "{" here!

丑陋的黑客,但我能想到的最好的。

【讨论】:

  • 哎呀,太丑了。我喜欢它。
  • 很难用那个宏继承...
  • @tibur:如果您需要继承,请向宏添加其他选项。
  • @Ock:Gross,请不要真的这样做。顺便说一句,__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 */ }; 一样使用它,效果会更好。但不要实际使用它。
【解决方案4】:

另一个替代方案可能如下,尽管它有自己的缺点

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 对象可能比比较字符串更快。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-28
  • 2019-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多