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;
}
相关推荐
念风零壹9 分钟前
C++ 内存避坑指南:如何用移动语义和智能指针解决“深拷贝”与“内存泄漏”
c++
智驱力人工智能14 分钟前
小区高空抛物AI实时预警方案 筑牢社区头顶安全的实践 高空抛物检测 高空抛物监控安装教程 高空抛物误报率优化方案 高空抛物监控案例分享
人工智能·深度学习·opencv·算法·安全·yolo·边缘计算
猫头虎25 分钟前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
YUJIANYUE44 分钟前
PHP纹路验证码
开发语言·php
仟濹1 小时前
【Java基础】多态 | 打卡day2
java·开发语言
孞㐑¥1 小时前
算法——BFS
开发语言·c++·经验分享·笔记·算法
Re.不晚1 小时前
JAVA进阶之路——无奖问答挑战2
java·开发语言
八零后琐话1 小时前
干货:程序员必备性能分析工具——Arthas火焰图
开发语言·python
月挽清风1 小时前
代码随想录第十五天
数据结构·算法·leetcode
3GPP仿真实验室1 小时前
【MATLAB源码】CORDIC-QR :基于Cordic硬件级矩阵QR分解
开发语言·matlab·矩阵