-
typeid查看全部
-
异常处理查看全部
-
RTTI:Run-Time Type Identification 运行时类型识别查看全部
-
dynamic_cast转换函数的注意事项: 为何使用dynamic_cast转换类指针时,需要虚函数呢。 Dynamic_cast转换是在运行时进行转换,运行时转换就需要知道类对象的信息(继承关系等)。 如何在运行时获取到这个信息——虚函数表。c++对象模型中,对象实例最前面的就是虚函数表指针, 通过这个指针可以获取到该类对象的所有虚函数,包括父类的。 因为派生类会继承基类的虚函数表,所以通过这个虚函数表,我们就可以知道该类对象的父类,在转换的时候就可以用来判断对象有无继承关系。 所以虚函数对于正确的基类指针转换为子类指针是非常重要的。查看全部
-
假如鸟类和飞机都继承了flyable这个接口类,为了可以实现bird和plane自己特有的方法,我们可以用到rtti技术 如图,在通过flyable *obj=new Bird时,然后把obj传入函数doSomething中,可以通过第二行代码打印出obj对象的类型(因为*obj代表obj这个对象),第三行代码判断如果*obj的类型是鸟类,就把obj这个接口类型指针(flyable指针)转化为鸟类的指针。 注意:1只有把它转化为鸟类的指针,才可以通过这个指针调用鸟类的特有的成员函数 2牢记转化的写法 Bird *bird=dynamic_cast<Bird*>(obj);查看全部
-
为什么要把一个类定义为抽象类,我们在定义类的时候,有的类概念很抽象,比如我们可以定义一个名字叫“物体”的类,显然物体这个概念十分抽象,它的许多方法需要通过他的子类才可以具体描述清楚。 一个抽象类之所以叫抽象类,是因为它里面有一个或以上的纯虚函数,纯虚函数的写法是virtual 函数返回类型 函数名()=0 ,纯虚函数里面不用写任何代码。 当我们定义了一个纯虚函数,他同样会在虚函数表中出现,如图calcPerimeter ptr就是纯虚函数的指针,他的只是0(意思就是他没有指向代码区,不会实现任何方法)。他这样的目的是为了让子类在继承他的时候,再实现他的方法。 例如circle继承了shape,circle为了可以计算周长,定义了一个叫calcPerimeter的方法,因此把他父类shape的纯虚函数calcPerimeter覆盖了,这样就可以通过子类circle来计算周长。 注意:1、抽象类的子类也可以是抽象类(当子类仍然有未能实现的纯虚函数时,子类就仍然是抽象类) 2、抽象类无法被实例化查看全部
-
虚析构函数的实现原理: 当我们在父类的shape的析构函数中前加上virtual,父类的虚函数表就会加上一个~shape_ptr的指针,而子类的析构函数前面系统也会自动加上virtual,变成virtual ~circle()。而子类的虚函数表中,也会加上虚析构函数~circle_ptr的指针。 当我们释放通过Shape *p=new Circle来实例化的对象时,通过circle虚函数表可以找到circle的析构函数并执行,然后再通过shape的虚函数表找到shape的析构函数并执行。 因此定义了虚析构函数时,先执行子类的析构函数,再执行父类的析构函数查看全部
-
当一个对象里面一个数据成员都没有的时候,是否意味着该对象不占用内存呢,显然不是,如图: shape对象没有数据成员,但是仍占用1个字节(因为对象至少要占用一个字节来声名自己的存在) 而circle中有一个int的成员,所以占了4个字节查看全部
-
当circle继承了父类shape时,虽然没有定义有关virtual的虚函数,但是他继承了父类的virtual,所以他也自动生成了一个虚函数表和虚函数指针(子类的虚函数表和父类的虚函数表的地址不一样),而这个虚函数表由于继承了父类的虚函数,所以里面有同样有一个计算面积的虚函数指针(calcArea_ptr),而且这指针的指向都是和父类的calcArea_ptr一摸一样。 当我们在子类circle中又重新定义了一个计算面积的虚函数calcArea时,子类的虚函数表的有关计算面积的指针(calcArea_ptr)原本指向父类的calcArea方法的值就会被覆盖,变成指向子类定义的计算面积的地方。查看全部
-
虚函数的实现原理: 在shape(父类)中有一个计算面积的虚函数calcArea,在实例化shape的对象时,系统检测到shape里面有虚函数,于是就会自动创建一个虚函数表,并且自动创建了一个虚函数表指针指向该表的首地址(对于我们来说上面的步骤我们是看不到的,是系统自己自动生成的)。在该虚函数表中,存在着所有shape类的虚函数的指针,我们可以找到计算面积的虚函数的指针(calcArea_ptr)也在里面,这个calcArea_ptr指向shape定义的计算面积的方法。查看全部
-
在写析构函数的时候,最好是在析构函数的前面加上一个virtual的关键字,因为我们不知道在以后继承的时候子类会不会在析构函数中进行销毁指针和释放内存的操作,在父类的析构函数前面加上virtual可以使子类的析构函数被调用,防止内存泄漏查看全部
-
动态多态和静态多态的区别(注意这些多态都出现在类里面,因为没有了继承就没有多态): 静态多态(早绑定):静态多态主要通过函数和运算符重载来实现,例如函数void go(int a){}和void go(){}这两个函数的名字一样,但是在编译的时候就可以根据go()里面有无输入参数区分出到底执行哪个方法 动态多态(晚绑定):例如父类father有个方法名字叫go(){“父类的go”}; 子类son有个方法也叫go(){“son的go”}; 子类daughter有个方法也叫go(){“daughter的go”}; father *p1=new son; father *p2=new daughter; 然后当我们执行 p1->go(); p2->go(); 输出的结果都只是父类的go;如果想实现输出"son的go"和"daughter的go",就需要在父类的go()方法得前面加上关键字virtual变成。这样再输入p1->go();p2->go();就可以输出"son的go"和"daughter的go"查看全部
-
virtual关键字使用的限制: 1.不能使用普通的函数,只能是类的成员函数 2.不能使用于静态成员函数 3.不能使用于构造函数 4.不能适用于内联函数查看全部
-
typeid与dynamic_cast用法查看全部
-
typeid注意事项查看全部
举报
0/150
提交
取消