类型ID,如何仅获取类型名称

typeid, how to get just type name only

本文关键字:取类型 何仅获 ID 类型      更新时间:2023-10-16

示例代码:

MainWindow::MainWindow(QWidget *parent) {
QString strTemp = typeid(this).name();
qDebug() << strTemp;
}

我只想获取类名,在上面的例子中,我只追求"MainWindow",我得到的是:

class MainWindow *

当然,我可以编写一个例程,该例程采用此字符串,然后删除仅隔离类名的类和指针部分。 有什么东西已经这样做了吗?

在没有任何标准例程的情况下,这就是我所做的:

QString strTemp = typeid(this).name();
qDebug() << strTemp;
QStringList lstParts = strTemp.split(" ");
if ( lstParts.length > 1 ) {
strTemp = lstParts[1];
}
qDebug() << strTemp;

以上结果仅显示类型名称。 最后我只需要__FUNCTION__给出类名和方法,从中调用它将得到:

MainWindow::MainWindow

cppreference 对std::type_info::name()说了以下内容:

返回一个实现定义的以 null 结尾的字符串,其中包含类型的名称。不提供任何保证;特别是,返回的字符串对于几种类型可以是相同的,并且可以在同一程序的调用之间更改。

因此,您在一个编译器下获得class MainWindow作为输出的事实并不意味着您将在不同的编译器(甚至是相同但更新的版本(下获得相同的输出。

为什么不使用boost::typeindex::type_id_with_cvrplus使用某些类型特征,例如remove_pointer_t来获得所需的结果?

#include <iostream>
#include <sstream>
#include <string>
#include <boost/type_index.hpp>
class MainWindow {
public:
void test()
{
std::ostringstream os;
os << 
boost::typeindex::type_id_with_cvr<std::remove_pointer_t<decltype(this)>>().pretty_name() 
;
std::string s = os.str(); // easy transform to QString
std::cout << s << std::endl;
}
};
int main()
{
MainWindow{}.test(); // as output MainWindow
return 0;
}

完整演示

你真的不应该依赖std::typeid,也不应该依赖 boost 或任何其他仅C++库。它们都不保证你会在不同的编译器上得到类型名,尤其是对于损坏的类型。使用虚函数甚至RTTI也可以影响类型的名称。没有什么能阻止编译器将"MainWindow"重命名为"CellarDoor"。到目前为止,唯一的方法是使用某种反射(还不是C++的一部分(或一些预处理器。ComicSansMS提供了一个很好的答案,您可以在其中推出自己的简单反射实现。

但是,由于您使用的是 QT,因此您可以使用 QT 元对象来实现此目的。它实际上有一种专用于此确切目的的方法;类名。

QMetaObject::className(( 在运行时以字符串形式返回类名,而无需通过C++编译器提供本机运行时类型信息 (RTTI( 支持。

只需致电metaObject()->className()

MainWindow::MainWindow(QWidget *parent) {
qDebug() << metaObject()->className();
}

Moc 在任何编译器之前运行,并将类名烘焙到代码中。查看 moc 生成的代码,您将看到类似以下内容:

static const qt_meta_stringdata_MainWindow_t qt_meta_stringdata_MainWindow = {
{
QT_MOC_LITERAL(0, 0, 10), // "MainWindow"
QT_MOC_LITERAL(1, 11, 13), // "buttonClicked"
QT_MOC_LITERAL(2, 25, 0) // ""
},
"MainWindowbuttonClicked"
};
std::type_info::name()

与此类任务不匹配。正如@pkrysiak的回答所指出的那样,此函数的返回值是实现定义的,因此不可能将其剥离为类型名称,因为它以可移植的方式出现在源代码中。

在这种情况下,更好的方法是滚动自己的反射机制,这将使您完全控制类型字符串。不幸的是,该语言目前没有为此提供很多支持,因此由此产生的机制将有点黑客攻击。例如,您可以执行以下操作:

#define ENABLE_REFLECTION_TYPE_NAME(class_name)                 
inline constexpr char const* type_name(class_name const&) {     
return #class_name;                                         
}
class Foo {};
ENABLE_REFLECTION_TYPE_NAME(Foo)
ENABLE_REFLECTION_TYPE_NAME(MainWindow)
MainWindow::MainWindow(QWidget *parent) {
QString strTemp = type_name(*this);
qDebug() << strTemp;             // prints "MainWindow"
Foo f;
QString strTemp2 = type_name(f);
qDebug() << strTemp2;            // prints "Foo"
}