C++_Primer_chapter18 2. 运行时类型识别

来源:互联网 发布:淘宝批发商诈骗 编辑:程序博客网 时间:2024/05/16 18:20

通过运行时类型识别(RTTI),程序能够使用基类的指针或引用来检索这些指针或引用所指向对象的实际派生类型

通过下面两个操作符提供RTTI( dynamic_cast 与typeid):

一、dynamic_cast

#include <iostream>class base {public:virtual ~base() {}virtual void isWhat() {std::cout << "base" << std::endl;}};class derived: public base {public:void isWhat() {std::cout << "derived" << std::endl;}};int main() {base* bPtr = new derived();base& bRef = *bPtr;/*对于指针,如果转化失败,则将指针置为NULL*/if (derived* derPtr = dynamic_cast<derived*>(bPtr)) {derPtr->isWhat();}else {/* derPtr == NULL*/}/*对于引用类型,因为没有NULL,所以直接抛出bad_cast异常*/try {derived& derRef = dynamic_cast<derived&>(bRef);derRef.isWhat();}catch (std::bad_cast& e) {/* throw a bad_cast exception*/}return 0;}

二、typeid

int main() {base* bPtr = new derived();base& bRef = *bPtr;if (typeid(*bPtr) == typeid(derived)) { // is "*bPtr" not "bPtr"bPtr->isWhat();}if (typeid(bRef) == typeid(*bPtr)) {bRef.isWhat();}return 0;}
注意:对于没有虚函数的类,typeid返回的是指针的静态类型。


三、type_info

与typeid相关的一个概念,是type_info类。创建type_info类唯一对象的方法是使用typeid操作符。

至少提供了4个函数:t1==t2,  t1!=t2,  t1.name(),  t1.before(t2)。

int main() {base* bPtr = new derived();base& bRef = *bPtr;if (typeid(*bPtr) == typeid(derived)) { // is "*bPtr" not "bPtr"bPtr->isWhat();}if (typeid(bRef) == typeid(*bPtr)) {bRef.isWhat();}std::cout<<typeid(*bPtr).name()<<std::endl;base *ptr = new base();std::cout << typeid(*bPtr).before(typeid(*ptr)) << std::endl; // falsestd::cout << typeid(*ptr).before(typeid(*bPtr)) << std::endl; // true, 继承关系的先后顺序return 0;}

四、RTTI的使用

假设类Derived继承自Base,并且添加了一些其他的数据成员,我们要为这个继承派生体系定义相等操作符,但是由于基类和派生类之间的转化关系,我们很难确定比较操作符的实际类型。所以,两个所以我们需要在比较操作时,先1)确定两个操作数的类型是否相同。如果不同,直接返回假,如果相同,那么2)再比较它们的数据是否相等。

class Base {friend bool operator==(const Base& lhs, const Base& rhs);public:explicit Base(int b): base_elem(b) { // explicit 只能用于类内部的构造函数的申明上面}virtual ~Base() {}private:int base_elem;protected:virtual  bool equal(const Base& rhs) const { // 只比较base类成员,其他不管return rhs.base_elem == base_elem;}};class Derived : public Base {friend bool operator==(const Base& lhs, const Base& rhs);public:Derived(int d, int b) : derived_elem(d), Base(b) {}virtual ~Derived() {}private:int derived_elem;protected: virtual bool equal(const Base& rhs) const { if (const Derived* ptr = dynamic_cast<const Derived*>(&rhs))return this->Base::equal(*ptr) && (derived_elem == ptr->derived_elem);elsereturn false;}};// 简化了代码,无须再对 const Derived& 形参进行重载bool operator == (const Base& lhs, const Base& rhs) {return (typeid(lhs) == typeid(rhs)) && (lhs.equal(rhs));}






0 0
原创粉丝点击