欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 文化 > 基础5 C++中的多态与RTTI(Run Time Type Identification)

基础5 C++中的多态与RTTI(Run Time Type Identification)

2025/7/3 22:37:54 来源:https://blog.csdn.net/qq_40178082/article/details/144637411  浏览:    关键词:基础5 C++中的多态与RTTI(Run Time Type Identification)

一、 运行时多态

struct Test1 { virtual void vfunc() {...}};
struct Test2: public Test1 { virtual void vfunc() {...}};Test2 testb;Test1 testc=testb;    // 非多态
Test* testd=&testb;   // 多态

为什么上面一个是多态,一个不是多态?

因为第一个转换的对象之间的转换(虚表变了),第二个是指针的重新解析(虚表没有变

#include <iostream>
#include <typeinfo>class A
{
public:A(){data1_ = new int();data2_ = new int();}virtual void vAfunc1() { std::cout << "A::vAfunc1()" << std::endl; };virtual void vAfunc2() { std::cout << "A::vAfunc2()" << std::endl; };void func1() { std::cout << "A::func1()" << std::endl; };void func2() { std::cout << "A::func2()" << std::endl; };virtual ~A(){std::cout << "A::~A" << std::endl;delete data1_;delete data2_;}private:int *data1_{};int *data2_{};
};class B : public A
{
public:B(){data3_ = new int();}virtual void vAfunc1() override { std::cout << "B::vAfunc1()" << std::endl; };virtual void vBfunc1() { std::cout << "B::vBfunc1()" << std::endl; };virtual void vBfunc2() { std::cout << "B::vBfunc2()" << std::endl; };void func2() { std::cout << "B::func2()" << std::endl; };virtual ~B(){std::cout << "B::~B" << std::endl;delete data3_;}private:int *data3_{};
};

 

 当你通过基类指针或引用删除一个派生类对象时,如果没有虚析构函数,编译器只会调用基类的析构函数,而不会调用派生类的析构函数。这会导致派生类中的资源无法正确释放,从而引发资源泄漏。

二、RTTI

由于多态的存在,一个函数的传入参数如果是一个父类指针(引用),有时候我们需要获得参数到底是哪一个子类。可以通过typeinfo来进行查询

// 方式1
std::type_info *base_type = (std::type_info *)*((int64_t *)*(int64_t *)(&a) - 1);
std::cout << "typeinfo is:" << base_type->name() << std::endl;
// 方式2
std::cout << "the result of typeid(Base).name():" << typeid(A).name() << std::endl;

2.1 typeid操作符,用于返回指针和引用所指向的实际类型

#include <iostream>
#include <typeinfo>class A
{
public:A(){data1_ = new int();data2_ = new int();}virtual void vAfunc1() { std::cout << "A::vAfunc1()" << std::endl; };virtual void vAfunc2() { std::cout << "A::vAfunc2()" << std::endl; };void func1() { std::cout << "A::func1()" << std::endl; };void func2() { std::cout << "A::func2()" << std::endl; };virtual ~A(){std::cout << "A::~A" << std::endl;delete data1_;delete data2_;}private:int *data1_{};int *data2_{};
};class B : public A
{
public:B(){data3_ = new int();}virtual void vAfunc1() override { std::cout << "B::vAfunc1()" << std::endl; };virtual void vBfunc1() { std::cout << "B::vBfunc1()" << std::endl; };virtual void vBfunc2() { std::cout << "B::vBfunc2()" << std::endl; };void func2() { std::cout << "B::func2()" << std::endl; };virtual ~B(){std::cout << "B::~B" << std::endl;delete data3_;}private:int *data3_{};
};class C : public A
{
public:C(){data4_ = new int();}virtual void vAfunc1() override { std::cout << "C::vAfunc1()" << std::endl; };void func3() { std::cout << "C::func3()" << std::endl; };virtual ~C(){std::cout << "C::~C" << std::endl;delete data4_;}private:int *data4_{};
};void test(A *a)
{if (typeid(*a) == typeid(A)){A *pa = reinterpret_cast<A *>(a);pa->func1();}if (typeid(*a) == typeid(B)){B *pb = reinterpret_cast<B *>(a);pb->func2();}if (typeid(*a) == typeid(C)){C *pc = reinterpret_cast<C *>(a);pc->func3();}
}int main()
{A *base = &b;test(base);C c;base = &c;test(base);return 0;
}
  • typeid返回的std::type_info删除了靠北构造,所以只能接收指针/引用

  • typeid的返回值会忽略cv限定符

2.2 dynamic_cast<type*>(e) 将基类型的指针或引用安全的转换为派生类指针或引用

struct Base{ 存在虚函数 }
struct A : public Base { ... }A a;
Base b;Base* b_ptr=dynamic_cast<Base *>(& a); // 成功转换
A* a_ptr=dynamic_cast<A *>(& b);       // nullptr
A* c_ptr=dynamic_cast<A *>(b_ptr);     // 成功转换

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com