C++类型判断

一、基础场景:编译期类型判断(静态类型检查)

C++ 是静态类型语言,大部分类型判断可以在编译期完成,这也是最常用、效率最高的方式。

1. typeid 运算符(最直接的类型判断)

typeid 是 C++ 内置运算符,能返回表示类型信息的 std::type_info 对象,核心用于:

  • 判断两个变量的类型是否相同
  • 获取类型的名称(注意:名称格式因编译器而异,仅作参考)

完整代码示例

cpp

运行

复制代码
#include <iostream>
#include <typeinfo>  // 必须包含此头文件

int main() {
    // 基础类型判断
    int a = 10;
    double b = 3.14;
    std::string c = "test";

    // 1. 判断类型是否相同
    if (typeid(a) == typeid(int)) {
        std::cout << "a 是 int 类型" << std::endl;
    }
    if (typeid(b) != typeid(a)) {
        std::cout << "b 和 a 类型不同" << std::endl;
    }

    // 2. 获取类型名称(编译器相关,如GCC显示"i"代表int,MSVC显示"int")
    std::cout << "a 的类型名:" << typeid(a).name() << std::endl;
    std::cout << "c 的类型名:" << typeid(c).name() << std::endl;

    // 3. 多态场景(注意:需是虚函数类,否则只识别静态类型)
    class Base { virtual void func() {} };
    class Derived : public Base {};
    Base* ptr = new Derived();
    std::cout << "ptr 指向的实际类型:" << typeid(*ptr).name() << std::endl;  // 输出Derived

    delete ptr;
    return 0;
}

关键说明

  • typeid非多态类型(无虚函数的类)只会返回变量的静态类型(声明类型);
  • 多态类型(有虚函数的类)会返回对象的实际类型(动态类型);
  • 类型名称(name())是编译器自定义的,比如 GCC 中int显示为istd::string显示为Ss,仅用于调试,不要用于逻辑判断。
2. 模板特化 /std::is_same(编译期精确判断)

如果需要在编译期精准判断类型(比如写通用模板函数时),推荐用 C++11 引入的 std::is_same(头文件 <type_traits>),效率更高且更可靠。

完整代码示例

cpp

运行

复制代码
#include <iostream>
#include <type_traits>  // 核心头文件

// 通用模板函数
template <typename T>
void checkType(T value) {
    if constexpr (std::is_same_v<T, int>) {  // C++17的is_same_v,等价于is_same<T,int>::value
        std::cout << "类型:int,值:" << value << std::endl;
    } else if constexpr (std::is_same_v<T, double>) {
        std::cout << "类型:double,值:" << value << std::endl;
    } else if constexpr (std::is_same_v<T, std::string>) {
        std::cout << "类型:string,值:" << value << std::endl;
    } else {
        std::cout << "未知类型" << std::endl;
    }
}

int main() {
    checkType(10);          // 输出:类型:int,值:10
    checkType(3.14);        // 输出:类型:double,值:3.14
    checkType(std::string("hello"));  // 输出:类型:string,值:hello

    // 额外:判断是否为某类的子类(编译期)
    class Base {};
    class Derived : public Base {};
    std::cout << "Derived是否是Base的子类:" << std::is_base_of_v<Base, Derived> << std::endl;  // 输出1(true)
    return 0;
}

关键说明

  • std::is_same<T1, T2>::value 返回布尔值,判断 T1 和 T2 是否是完全相同的类型;
  • if constexpr(C++17)确保编译期就剔除不匹配的分支,无运行时开销;
  • 配套工具:std::is_int(是否整型)、std::is_float(是否浮点型)、std::is_pointer(是否指针)等,满足各类基础类型判断。

二、进阶场景:运行期类型判断(动态类型检查)

主要用于多态场景(父类指针 / 引用指向子类对象),核心用 dynamic_cast

完整代码示例

cpp

运行

复制代码
#include <iostream>

class Base {
public:
    virtual ~Base() {}  // 必须有虚函数,否则dynamic_cast无法使用
};

class Derived1 : public Base {
public:
    void derived1Func() { std::cout << "这是Derived1类型" << std::endl; }
};

class Derived2 : public Base {
public:
    void derived2Func() { std::cout << "这是Derived2类型" << std::endl; }
};

int main() {
    Base* ptr = new Derived1();

    // 1. dynamic_cast判断类型(指针版:失败返回nullptr)
    if (Derived1* d1 = dynamic_cast<Derived1*>(ptr)) {
        d1->derived1Func();  // 成功,调用子类方法
    } else if (Derived2* d2 = dynamic_cast<Derived2*>(ptr)) {
        d2->derived2Func();
    }

    // 2. 引用版:失败抛出std::bad_cast异常
    try {
        Derived1& ref = dynamic_cast<Derived1&>(*ptr);
        ref.derived1Func();
    } catch (const std::bad_cast& e) {
        std::cout << "类型转换失败:" << e.what() << std::endl;
    }

    delete ptr;
    return 0;
}

关键说明

  • dynamic_cast 仅适用于有虚函数的类(多态类型);
  • 指针类型转换失败返回 nullptr,引用类型转换失败抛出 std::bad_cast 异常;
  • 运行期类型判断有一定性能开销,非必要不使用(优先用多态直接调用虚函数)。

三、避坑提醒

  1. 不要依赖 typeid().name() 的返回值做逻辑判断(编译器差异大);
  2. 编译期判断(std::is_same)优先于运行期判断(dynamic_cast/typeid),效率更高;
  3. dynamic_cast 必须有虚函数,否则编译报错;
  4. 模板场景下,优先用编译期类型判断(模板特化 /type_traits),避免运行时开销。

总结

  1. 编译期类型判断 :用 std::is_same/std::is_base_of 等(<type_traits>),无运行时开销,适合模板、基础类型判断;
  2. 运行期类型判断 :多态场景用 dynamic_cast(最可靠),简单类型对比用 typeid(注意多态 / 非多态区别);
  3. 优先使用编译期判断,仅在多态动态类型识别时用运行期判断。
相关推荐
Anastasiozzzz7 小时前
Java Lambda 揭秘:从匿名内部类到底层原理的深度解析
java·开发语言
刘琦沛在进步7 小时前
【C / C++】引用和函数重载的介绍
c语言·开发语言·c++
机器视觉的发动机7 小时前
AI算力中心的能耗挑战与未来破局之路
开发语言·人工智能·自动化·视觉检测·机器视觉
HyperAI超神经7 小时前
在线教程|DeepSeek-OCR 2公式/表格解析同步改善,以低视觉token成本实现近4%的性能跃迁
开发语言·人工智能·深度学习·神经网络·机器学习·ocr·创业创新
R_.L7 小时前
【QT】常用控件(按钮类控件、显示类控件、输入类控件、多元素控件、容器类控件、布局管理器)
开发语言·qt
Zach_yuan7 小时前
自定义协议:实现网络计算器
linux·服务器·开发语言·网络
我在人间贩卖青春7 小时前
C++之this指针
c++·this
云姜.7 小时前
java多态
java·开发语言·c++
CoderCodingNo8 小时前
【GESP】C++五级练习题 luogu-P1865 A % B Problem
开发语言·c++·算法
陳10308 小时前
C++:红黑树
开发语言·c++