类型ID,如何仅获取类型名称
typeid, how to get just type name only
示例代码:
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_cvr
plus使用某些类型特征,例如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) // ""
},
"MainWindow buttonClicked "
};
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"
}
- 仅在函数模板中为那些定义了函数的类型执行函数
- 如何允许模板参数中的类类型,仅当它有两个基类时
- 标准对此指向成员函数类型模板参数有何说明?是我的代码有误,还是 MSVS 16.6 有问题?
- std::ifstream 在读取文件中最后一项时设置 eofbit,但仅在读取数值类型时发生
- 仅当类型为 std::complex 时,才进行缩放
- 类型ID,如何仅获取类型名称
- 如何使虚函数接受仅在派生类中定义的数据类型?
- 为什么C++不允许两个同名的函数/类模板,区别仅在于非类型模板参数(整型)的类型?
- 重载函数仅在返回类型上有所不同
- 在从仅移动类型派生的类中定义析构函数在使用 std::vector emplace_back或push_back创建时会
- 强制复制(然后销毁)仅移动类型
- 仅使用类型参数的可变参数模板
- boost multi_index - 如果元素类型仅支持移动语义,如何遍历它?
- 使用迭代器成员函数是否仅适用于某些向量类型"empty()"?
- static_cast为仅移动类型的叮当与 GCC
- 为什么类型铸件仅在这句话中失败
- 如何约束参数类型以仅允许 std::initializer_list<size_t> 或 std::array<size_t, N>?
- std::map,自定义键类型,仅对一个变量进行排序
- C++类型 重载仅部分起作用
- cd库:在推送自定义类型的派生类型时(仅在发布模式下),michael_deque会导致崩溃