c++ rtti判断基类指针指向的真实对象类型

 更新时间:2023年08月28日 10:30:31   作者:会灰的飞猫  
这篇文章主要为大家介绍了c++ 判断基类指针指向的真实对象类型示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

正文

在 c++ 面向对象使用中,我们常常会定义一个基类类型的指针,在运行过程中,这个指针可能指向一个基类类型的对象,也可能指向的是其子类类型的对象,那现在问题来了,我们如何去判断这个指针到底执行了一个什么类型的对象呢?

今天我们就聊一下这个问题,首先我们要区分是否允许 RTTI,据此有不同办法。

允许使用 RTTI

在打开 rtti 的场景下,可以使用 dynamic_cast 和 typeid 这两个运算符来判断对象的真实类型。

使用 dynamic_cast

dynamic_cast 用于在运行时进行多态类型检查和转换,它可以将指向基类的指针转换为指向派生类的指针或引用。如果转换成功,则说明对象属于目标类或其派生类。如果转换失败,则返回空指针。
我们看如下例子,我们想判断指针 basePtr 是否指向了 Child2 类型的对象。总共进行了两次测试,第一次让该指针指向了 Child1 类型的对象,第二次则是指向了 Child2 类型的对象。

#include <iostream>
class Basic {
public:
    virtual void say() {
        std::cout << "我是基类" << std::endl;
    }
};
class Child1 : public Basic {
public:
    void say() {
        std::cout << "我是 child 1" << std::endl;
    }
};
class Child2 : public Basic {
public:
    void say() {
        std::cout << "我是 child 2" << std::endl;
    }
};
int main()
{
    Basic* basePtr;
    basePtr = new Child1();
    if (dynamic_cast<Child2*>(basePtr)) {
        std::cout << "[test 1]指针指向了 Child2 类型对象" << std::endl;
    } else {
        std::cout << "[test 1]指针没有指向 Child2 类型对象" << std::endl;
    }
    delete basePtr;
    basePtr = new Child2();
    if (dynamic_cast<Child2*>(basePtr)) {
        std::cout << "[test 2]指针指向了 Child2 类型对象" << std::endl;
    } else {
        std::cout << "[test 2]指针没有指向 Child2 类型对象" << std::endl;
    }
    delete basePtr;
}

让我们一起看看两次的打印,这是符合我们的预期的,使用 dynamic_cast 可以判断一个基类类型的指针是否指向了某个具体类类型。

在这里,有的朋友会好奇,我为什么添加了 say() 这么一个方法,凑数吗?确实是,就是凑数的dynamic_cast 是用于多态运行时的类型检查,如果我不增加这么一个方法,并且在基类中添加上 virtual 关键字,那就不存在多态,也就无从谈起运行时多态类型检查。下面是我将 virtual 去掉,或者干脆删除 say() 方法的编译结果。

使用 typeid

typeid 运算符返回一个 type_info 对象,该对象包含类型的相关信息。通过比较两个指针的类型信息,可以确定它们是否具有相同的类型。这里我们不用管 type_info 是什么东西,我们主要看看怎么用,下面继续看看刚刚的例子。

#include <iostream>
class Basic {
public:
    virtual void say() {
        std::cout << "我是基类" << std::endl;
    }
};
class Child1 : public Basic {
public:
    void say() {
        std::cout << "我是 child 1" << std::endl;
    }
};
class Child2 : public Basic {
public:
    void say() {
        std::cout << "我是 child 2" << std::endl;
    }
};
int main()
{
    Basic* basePtr;
    basePtr = new Child1();
    if (typeid(*basePtr) == typeid(Child2)) {
        std::cout << "[test 1]指针指向了 Child2 类型对象" << std::endl;
    } else {
        std::cout << "[test 1]指针没有指向 Child2 类型对象" << std::endl;
    }
    delete basePtr;
    basePtr = new Child2();
    if (typeid(*basePtr) == typeid(Child2)) {
        std::cout << "[test 2]指针指向了 Child2 类型对象" << std::endl;
    } else {
        std::cout << "[test 2]指针没有指向 Child2 类型对象" << std::endl;
    }
    delete basePtr;
}

运行结果,和刚刚使用 dynamic_cast 一样。我们这里是来判断基类指针是否指向了某个具体类对象,typeid 当然也可以用来判断两个指针指向的具体类类型是否相同,这里不再展开。

值得注意的是,使用 typeid 时,如果去掉基类方法中的 virtual 关键字,编译并不会报错,但运行结果肯定会错,此时因为不存在多态,该运算符始终会返回基类的信息。

不允许使用 RTTI

出于某些原因,你的项目可能禁用了 RTTI,那这个时候我们应该怎么判断基类指针指向的具体类呢?我们还能利用多态本身,就是给基类新增一个虚方法,子类在必要的时候来重写。

下面我们继续用刚刚的例子,一起看看代码吧。

#include <iostream>
class Basic {
public:
    virtual void say() {
        std::cout << "我是基类" << std::endl;
    }
    virtual bool isChild2() {
        return false;
    }
};
class Child1 : public Basic {
public:
    void say() {
        std::cout << "我是 child 1" << std::endl;
    }
};
class Child2 : public Basic {
public:
    void say() {
        std::cout << "我是 child 2" << std::endl;
    }
    bool isChild2() {
        return true;
    }
};
int main()
{
    Basic* basePtr;
    basePtr = new Child1();
    if (basePtr->isChild2()) {
        std::cout << "[test 1]指针指向了 Child2 类型对象" << std::endl;
    } else {
        std::cout << "[test 1]指针没有指向 Child2 类型对象" << std::endl;
    }
    delete basePtr;
    basePtr = new Child2();
    if (basePtr->isChild2()) {
        std::cout << "[test 2]指针指向了 Child2 类型对象" << std::endl;
    } else {
        std::cout << "[test 2]指针没有指向 Child2 类型对象" << std::endl;
    }
    delete basePtr;
}

我们新增了一个 isChild2() 的方法,用来判断该类是否是 Child2 类型,因为我这里只需要判断基类指针是否指向了 Child2 类型的对象,所以就直接增加了个 bool 返回值的接口进行判断了。在实际使用时,也可以返回枚举变量,分别对应例子中的三个类。

总结

当项目允许 RTTI 时,我们可以使用 dynamic_cast 和 typeid 运算符来判断一个基类指针指向的具体对象类型;当禁用 RTTI 时,我们就利用多态本身,为基类新增一个方法,用来获取类类型信息。

以上就是c++ rtti判断基类指针指向的真实对象类型的详细内容,更多关于c++ rtti判断基类指针指向的资料请关注脚本之家其它相关文章!

相关文章

  • c++算法进阶删除有序链表中的重复元素

    c++算法进阶删除有序链表中的重复元素

    这篇文章主要为大家介绍了c++算法进阶删除有序链表中的重复元素示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • C++实现LeetCode(18.四数之和)

    C++实现LeetCode(18.四数之和)

    这篇文章主要介绍了C++实现LeetCode(18.四数之和),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C语言strtod()函数案例详解

    C语言strtod()函数案例详解

    这篇文章主要介绍了C语言strtod()函数案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • linux c 获取本机公网IP的实现方法

    linux c 获取本机公网IP的实现方法

    本篇文章是对在linux中使用c语言获取本机公网IP的方法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • 深入理解堆排序及其分析

    深入理解堆排序及其分析

    本篇文章是对堆排进行了详细的分析以及介绍,需要的朋友参考下
    2013-05-05
  • 简单谈谈C++ 中指针与引用

    简单谈谈C++ 中指针与引用

    下面用通俗易懂的话来概述一下,指针-对于一个类型T,T*就是指向T的指针类型,也即一个T*类型的变量能够保存一个T对象的地址,而类型T是可以加一些限定词的,引用-引用是一个对象的别名,主要用于函数参数和返回值类型,符号X&表示X类型的引用。
    2015-09-09
  • c++中cin实现输入字符串方式

    c++中cin实现输入字符串方式

    这篇文章主要介绍了c++中cin实现输入字符串方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • 关于C++中菱形继承和虚继承的问题总结

    关于C++中菱形继承和虚继承的问题总结

    C++的三大特性为:封装,继承,多态。但是在继承中,存在一些使用方面的问题需要注意,下面这篇文章主要给大家总结介绍了关于C++中菱形继承和虚继承的问题,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-08-08
  • C++图像加载之libpng、FreeImage、stb_image详解

    C++图像加载之libpng、FreeImage、stb_image详解

    libpng、FreeImage、stb_image都是图像解析的开源库,这篇文章主要为大家详细介绍了这三者的使用方法,文中的示例代码讲解详细,需要的可以参考一下
    2023-06-06
  • 简单掌握C++编程中的while与do-while循环语句使用

    简单掌握C++编程中的while与do-while循环语句使用

    这篇文章主要介绍了C++编程中的while与do-while循环语句使用,区别就是while是先判断再执行,而do-while是先执行再判断,需要的朋友可以参考下
    2016-01-01

最新评论