c++中如何打印未知类型对象的类型

在 C++ 中要打印未知类型对象的类型名称,可以通过以下方法实现:

目录

[方法一:使用 typeid 和 name()(需包含 )](#方法一:使用 typeid 和 name()(需包含 ))

使用示例:

问题与改进:

[方法二:编译时类型名称(C++17 起)](#方法二:编译时类型名称(C++17 起))

使用示例:

[方法三:使用 Boost 库(跨平台)](#方法三:使用 Boost 库(跨平台))

对比总结:

注意事项:

完整示例(支持跨平台反修饰):


方法一:使用 typeidname()(需包含 <typeinfo>

cpp 复制代码
#include <iostream>
#include <typeinfo>

template <typename T>
void printType(const T& obj) {
    std::cout << "类型名称: " << typeid(obj).name() << std::endl;
}

使用示例:

cpp 复制代码
int main() {
    auto x = 3.14;
    printType(x);  // 输出类似 "d"(GCC)或 "double"(MSVC)
    return 0;
}

问题与改进:

  • 编译器差异

    • GCC/Clang 会返回名称修饰的字符串(如 i 表示 intd 表示 double

    • MSVC 会直接返回可读名称(如 int

  • Demangling(反修饰)

    cpp 复制代码
    #include <cxxabi.h>  // GCC/Clang 专用
    
    template <typename T>
    void printHumanReadableType(const T& obj) {
        int status;
        char* name = abi::__cxa_demangle(typeid(obj).name(), 0, 0, &status);
        std::cout << "可读类型: " << (status == 0 ? name : "未知类型") << std::endl;
        free(name);
    }

方法二:编译时类型名称(C++17 起)

cpp 复制代码
#include <string_view>

template <typename T>
constexpr std::string_view type_name() {
    #if defined(__clang__)
    return __PRETTY_FUNCTION__;
    #elif defined(__GNUC__)
    return __PRETTY_FUNCTION__;
    #elif defined(_MSC_VER)
    return __FUNCSIG__;
    #endif
}

template <typename T>
void printTypeAtCompileTime() {
    constexpr auto prefix = sizeof("auto type_name() [T = ") - 1;
    constexpr auto suffix = sizeof("]") - 1;
    constexpr auto name = type_name<T>();
    std::cout << "编译时类型: " 
              << name.substr(prefix, name.size() - prefix - suffix)
              << std::endl;
}

使用示例:

cpp 复制代码
printTypeAtCompileTime<std::vector<int>>();
// 输出类似 "std::vector<int, std::allocator<int>>"

方法三:使用 Boost 库(跨平台)

cpp 复制代码
#include <boost/type_index.hpp>

template <typename T>
void printTypeWithBoost(const T& obj) {
    using boost::typeindex::type_id_with_cvr;
    std::cout << "Boost 类型: "
              << type_id_with_cvr<T>().pretty_name()
              << std::endl;
}

对比总结:

方法 优点 缺点
typeid 简单直接 需要处理名称修饰
编译时方法 无需运行时开销 依赖编译器特定宏
Boost 库 输出美观、跨平台 需要额外安装依赖库

注意事项:

  1. 多态类型typeid 对多态类型会返回动态类型

    cpp 复制代码
    class Base { virtual void foo() {} }; // 必须包含虚函数
    class Derived : public Base {};
    
    Base* obj = new Derived;
    std::cout << typeid(*obj).name(); // 输出 Derived 的类型
  2. 类型修饰

    cpp 复制代码
    const int& x = 42;
    printType(x);  // 可能输出 "i" 而非 "const int&"
  3. 平台兼容性

    cpp 复制代码
    #if defined(__GNUC__) && !defined(__clang__)
    // GCC 专用处理
    #elif defined(_MSC_VER)
    // MSVC 专用处理
    #endif

完整示例(支持跨平台反修饰):

cpp 复制代码
#include <iostream>
#include <typeinfo>
#include <cxxabi.h>

template <typename T>
std::string demangle() {
    int status = -1;
    const char* name = typeid(T).name();
    char* demangled = abi::__cxa_demangle(name, NULL, NULL, &status);
    std::string result = (status == 0) ? demangled : name;
    free(demangled);
    return result;
}

int main() {
    const std::vector<double> vec;
    std::cout << "Demangled type: " << demangle<decltype(vec)>() << std::endl;
    // 输出: std::vector<double, std::allocator<double> >
    return 0;
}
相关推荐
兰令水1 小时前
leecodecode【面试150】【2026.6.14打卡-java版本】
java·算法·面试
yaoxin5211237 小时前
434. Java 日期时间 API - Period 基于日期的时间段
java·开发语言·python
凡人叶枫8 小时前
Effective C++ 条款30:透彻了解 inlining 的里里外外
linux·开发语言·c++·嵌入式开发·effective c++
noipp8 小时前
推荐题目:洛谷 P10907 [蓝桥杯 2024 国 B] 蚂蚁开会
c语言·c++·算法·编程·洛谷
学逆向的8 小时前
C++纯虚函数
开发语言·c++·网络安全
程序员二叉8 小时前
【JUC】ThreadLocal底层原理|内存泄漏|弱引用|跨线程传递方案
java·开发语言·面试·职场和发展·juc
程序员二叉8 小时前
【JUC】线程池全套深度详解|参数|流程|拒绝策略|调优|异常处理
java·开发语言·jvm·算法·面试·juc
青山木9 小时前
Hot 100 --- 轮转数组
java·数据结构·算法
徐小夕9 小时前
Loop Engineering 深度解析与实战指南(全网最全)
前端·算法·github
凡人叶枫9 小时前
Effective C++ 条款22:将成员变量声明为 private
linux·开发语言·c++