-
判断对象类型
查看全部 -
抽象类无法实例化对象
查看全部 -
虚函数调用过程
查看全部 -
子类中同名函数也要加关键字
查看全部 -
在父类中把想要实现多态的成员函数,定义为虚函数
查看全部 -
动态多态用到的虚函数
查看全部 -
什么是多态
查看全部 -
【异常处理的关键字】try…catch… throw
try和catch可以是一对多的
常见的异常:数组下标越界、除数为0、内存不足
查看全部 -
【RTTI(Run-Time-Type-Identification)】运行时类型识别
void dosomething(Flyable *obj){ obj->takeoff(); obj->land(); //使用RTTI cout << typeid(*obj).name() << endl; //打印出指针obj实际指向的类型 if(typeid(*obj)==typeid(Bird)){ //如果当前obj指向一个Bird类型 Bird *bird=dynamic_cast<Bird *>(obj); //将obj转化为一个Bird*类型 bird->foraging(); //调用Bird类中的函数foraging(); } }
【dynamic_cast使用的注意事项】:
1、只能应用于指针的转换或引用的转换,而不是某个类型本身(<Bird *>要加上星号)
2、要转换的类型中必须包含虚函数
3、转换成功,则返回子类的地址;失败则返回NULL
【typeid使用的注意事项】:
1、返回一个type_info对象的引用
2、如果想通过基类的指针获得派生类的数据类型,则基类必须有虚函数
3、只能获取对象的实际类型
查看全部 -
【接口类】仅含有纯虚函数的类(没有任何数据成员,仅有成员函数且都是纯虚函数),在实际应用中更多地用来表达一种能力/协议
class Flyable{ public: virtual void takeoff()=0;//起飞 virtual void land()=0;//降落 };
查看全部 -
class Shape{ public: virtual double calcArea(){return 0};//虚函数 virtual double calcPerimeter()=0;//纯虚函数(在后面加“=0”) }
【抽象类】含有纯虚函数的类,无法实例化对象,其子类也可以是抽象类,也可以不是(只有当子类不是抽象类,即对所有函数都实现了,才可以用这个子类实例化对象)
查看全部 -
父类数据成员中会有一个【虚函数表指针】,指向一个虚函数表,在表中相应虚函数(比如计算面积)的入口地址,从而找到当前定义的虚函数
当实例化一个子类的时候,由于当中没有定义虚函数,但是从父类中继承了,所以在实例化时会产生一个虚函数表(跟父类中的不是同一个),但是相应函数(比如计算面积)的函数指针是一样的(同样的入口地址)
但是如果子类中的相应函数是一个虚函数,则相应的函数指针就会覆盖父类的函数指针(不再是相同的入口地址)
【虚析构函数可以防止内存泄露的理论前提】执行完子类的析构函数就会执行父类的析构函数
查看全部 -
【动态多态的内存泄露问题】
使用delete销毁父类指针,只会执行父类的析构函数
销毁子类指针,会执行父类和子类的析构函数
但在多态中,是用一个父类的指针指向一个子类的内存,因此无法执行子类的析构函数
Shape *s1=new Circle(3,4,5.0);
使用【虚析构函数】来解决
virtual ~Shape();
【virtual在修饰函数时的限制】
1、不能修饰普通函数,必须是【某个类】的成员函数,不能是全局函数
2、不能修饰静态成员函数
virtual static int getCount(); //错误
3、不能修饰内联函数
inline virtual int eat();//计算机就会忽略掉inline关键字
4、不能修饰构造函数
查看全部 -
相同对象收到不同消息,或不同对象收到相同消息时产生的不同动作
1、早绑定/静态多态
public: int Area(int width); int Area(int width,int height); //互为重载
程序在编译阶段就已经确定到底要使用哪个函数了(传入参数的个数不同)
2、晚绑定/动态多态:必须以封装和继承为基础
用virtual关键词修饰成员函数(修饰想要实现多态的成员函数),使之成为虚函数
查看全部 -
面向对象的三大特征:封装、多态、继承
查看全部
举报