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. 优先使用编译期判断,仅在多态动态类型识别时用运行期判断。
相关推荐
2501_944521592 小时前
Flutter for OpenHarmony 微动漫App实战:推荐动漫实现
android·开发语言·前端·javascript·flutter·ecmascript
不绝1912 小时前
C#进阶:委托
开发语言·c#
喜欢喝果茶.2 小时前
跨.cs 文件传值(C#)
开发语言·c#
Yu_Lijing2 小时前
基于C++的《Head First设计模式》笔记——模式合作
c++·笔记·设计模式
zmzb01032 小时前
C++课后习题训练记录Day74
开发语言·c++
小冷coding2 小时前
【Java】Dubbo 与 OpenFeign 的核心区别
java·开发语言·dubbo
Coder_Boy_2 小时前
基于SpringAI的在线考试系统-智能考试系统-学习分析模块
java·开发语言·数据库·spring boot·ddd·tdd
2401_894828122 小时前
从原理到实战:随机森林算法全解析(附 Python 完整代码)
开发语言·python·算法·随机森林
玄同7652 小时前
Python「焚诀」:吞噬所有语法糖的终极修炼手册
开发语言·数据库·人工智能·python·postgresql·自然语言处理·nlp