2010-12-16 77 views
12

如果我定义一个类:如何获取类名?

class Blah {}; 

哪有我:

std::string const className = /* What do I need to do here? */; 
assert(className == "Blah"); 

我不认为typeid的()名称()是一个好主意,因为它是特定compiler implementation。 C++标准或Boost提供了什么吗?

注意:如果类是从Qt的QObject继承的,我可以很容易地使用QMetaObject::className()来获取类名。

回答

10

像这样:

class Blah { static std::string const className() { return "Blah"; }}; 

std::string const name = Blah::className(); 
assert(name == "Blah"); 

或者这样:

class Blah {}; 

template < typename T > struct name; 
template < > struct name<Blah> { static std::string value() { return "Blah"; }}; 

std::string const classname = name<Blah>::value(); 
assert(classname == "Blah"); 

票友:

#define DECLARE_NAMED_CLASS(Name) \ 
struct Name;\ 
template < > struct name<Name> { static std::string value() { return #Name; }};\ 
struct Name 

DECLARE_NAMED_CLASS(Blah) {}; 
std::string const className = name<Blah>::value(); 
... 

或者这样:

class Blah : QObject { Q_OBJECT }; 

或者这样:...... 或者这样:...

+6

另一种解决方案将被TYPEID()+还原函数。否则,你如何处理命名空间等? – 2010-12-16 23:00:39

+2

typeid不保证是不可升级的。 – quetzalcoatl 2012-09-03 21:32:52

+0

第一种情况是唯一严重的情况。它易读,易于维护和使用。第二个过度复杂化一个简单的问题。也许你宁愿使用REST api来调用web服务呢?第三个被认为是坏习惯。当涉及到良好的设计时,预处理器是最糟糕的,也是最不应该使用的。对于预处理器,我能想到的唯一合理用例是编译指示一次。 – nali 2017-12-05 22:25:55

1

我不认为有任何非编译器特定的解决方案,这种问题不涉及类声明中的大量宏(实际上,如果我正确理解了QT文档,您得到的字符串objectName实际上被分配了“by手“,我认为用moc创建的代码)。

另一方面,一般来说,检查一个对象的类是不是你不希望你做字符串比较,而是做一个typeid比较。

assert(typeid(YourObject)==typeid(Blah)); 

但可能你应该更好地解释你想要达到的目标。

3

测试一类通过看它的名字听起来非常像一个Java风格的方法对我来说,在C++中,你应该警惕的尝试应用相同图案!更好的方法是使用像boost::type_traits这样的东西,并且可能是is_same,并带有真实的类名。

1

我认为dynamic_cast可能是你在找什么。 它不会给你类的名字,但它会以你希望断言失败的方式失败,除非Blah的子类不会被捕获。

1

我不认为typeid()。name()是一个好主意,因为它是编译器 实现特定的。

是的,标准并不要求从实现中使用任何特定的命名,所以它甚至可以改变相同的编译器。

C++标准或Boost提供了什么吗?

有没有标准的设施,会返回类名称在一些canonic形式。

1

的QObject->元对象()方法是有效的Qt的除了所述基于的QGraphicsItem类,不继承QObject ...