ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

虚函数和 RTTI实现运行时多态

虚函数和 RTTI实现运行时多态 虚函数和RTTI是 C 实现运行时多态的两大核心机制。1. 虚函数Virtual Function什么是虚函数在基类中用virtual声明的成员函数。当通过基类指针或引用调用时实际执行的是对象真正类型动态类型对应的函数版本而不是指针/引用声明的类型静态类型。核心作用实现运行时多态动态绑定。简单原理实现层面含有虚函数的类会生成一张虚函数表vtable。每个对象会多一个隐藏的指针vptr指向自己类的 vtable。调用虚函数时通过 vptr 找到正确的函数地址再执行。示例#includeiostreamclassAnimal{public:virtualvoidspeak()const{// 虚函数std::coutAnimal speaks\n;}virtual~Animal()default;// 强烈建议虚析构};classDog:publicAnimal{public:voidspeak()constoverride{// 重写std::coutWoof!\n;}};classCat:publicAnimal{public:voidspeak()constoverride{std::coutMeow!\n;}};intmain(){Animal*a1newDog();Animal*a2newCat();a1-speak();// 输出 Woof!按动态类型调用a2-speak();// 输出 Meow!deletea1;deletea2;}重要规则点说明虚析构函数通过基类指针delete时必须虚析构否则只调用基类析构导致资源泄漏overrideC11 推荐使用明确表示重写防止拼写错误纯虚函数virtual void f() 0;使类成为抽象类不能实例化非虚函数始终按静态类型调用不会动态分派2. RTTIRuntime Type Information什么是 RTTI运行时类型信息。允许程序在运行时查询对象的真实类型。C 提供两个主要工具typeiddynamic_cast前提类型必须是多态类型至少有一个虚函数否则typeid和dynamic_cast只能看到静态类型。2.1typeid返回const std::type_info可用来比较类型。#includeiostream#includetypeinfoAnimal*pnewDog();if(typeid(*p)typeid(Dog)){std::cout这是一只狗\n;}std::couttypeid(*p).name()\n;// 实现定义可能是 3Dog 或 class Dog注意typeid对引用和指针解引用后的对象才有效地获取动态类型。2.2dynamic_cast安全向下转型在运行时检查转型是否合法成功 → 返回正确的指针/引用失败 → 指针返回nullptr引用抛出std::bad_castAnimal*pnewDog();// 向下转型if(Dog*ddynamic_castDog*(p)){d-speak();// 安全使用// 可以调用 Dog 特有的成员}else{std::cout不是 Dog\n;}// 引用版本失败会抛异常try{Dogddynamic_castDog(*p);}catch(conststd::bad_caste){std::cout转型失败\n;}dynamic_cast的常见用途安全地从基类指针转回派生类指针跨继承体系转型多继承时判断对象是否属于某个类型虚函数 vs RTTI 对比特性虚函数RTTItypeid / dynamic_cast目的调用正确的函数版本查询/检查真实类型性能很快一次间接调用稍慢需要查类型信息依赖虚函数表同样依赖虚函数多态类型使用场景日常多态调用需要知道具体类型时较少用使用建议优先使用虚函数绝大多数多态场景用虚函数就够了更清晰、更高效。少用 RTTI频繁使用dynamic_cast或typeid通常是设计不够好的信号可以用虚函数或 visitor 模式替代。必须虚析构只要类可能被基类指针删除就应该把析构函数声明为虚函数。抽象基类如果基类不应该被实例化就把关键接口写成纯虚函数。一句话总结虚函数→ 让“调用哪个函数”在运行时决定RTTI→ 让“对象到底是什么类型”在运行时可知两者都依赖“多态类型”有虚函数共同支撑 C 的运行时多态能力。
返回列表