1 structure和class的区别?
structure和class的唯一区别就是默认的访问控制不同,structure默认是public,class默认是Private;structure也可以有构造函数、析构函数、成员函数等。
2 继承体系中为什么将析构函数声明为虚函数?
当你可能通过基类指针删除派生类对象时,建议使用虚析构函数。这样保证在删除一个执行派生类的基类指针时,不会出现只删除了基类部分,而没有删除派生类部分而导致内存泄露。
3 析构函数可以为virtual型,构造函数则不能。那么为什么构造函数不能为虚呢?
1)从存储的角度看,虚函数对应一个执行vtable虚函数表的指针,都知道,这个指向vtable的指针其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过vtable来调用,可是对象还没有实例化,也就是内存空间还没有,怎么找vtable呢?所以构造函数不能是虚函数。
2)虚函数采用一种虚调用的办法。徐调用是一种可以在只有部分信息的情况下工作的机制,特别允许我们调用一个只知道接口而不知道其准备对象类型的函数。但是如果要创建一个对象,你势必要知道对象的准确类型,因此构造函数不能为虚。
3 为什么不把每个函数都声明为虚函数?
这是因为虚函数是有代价的:由于每个虚函数的对象必须维护一个指向虚函数表的指针,因此在使用虚函数的时候会产生一个系统开销。如果仅是一个很小的类,且不想派生其他类,那么根本没有必要使用虚函数。
4 什么是多态?
多态性可以简单地概况成一句话“一个接口,多个方法“,在程序运行过程中才决定调用的函数。多态性是面向对象编程领域的核心概念。多态是通过虚函数实现的。
虚函数就是允许被其子类重新定义的成员函数。而子类重新定义父类虚函数的做法,称为”覆盖“,或者称为”重写“。覆盖是指子类重新定义父类的虚函数的做法。而重组,是指允许存在多个同名函数,而这些函数的参数表不同(或者参数个数不同,或者参数类型不同,或者两者都不同)。其实,重载的概念并不属于”面向对象编程“。重载的实现是:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数(至少对编译器来说是这样的)。它们的地址在编译期就绑定了,是静态的,因此,重载与多态无关。真正与多态相关的是”覆盖“。当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态地调用属于子类的该函数,这样的函数调用在编译期间是如法确定的。因此,函数是在运行期绑定的。结论是:重载只是一种语言特性,与多态无关,与面向对象也无关!
封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类),它们的目的都是为了代码重用。而多态则是为了实现另一个目的——接口重用!
5 重载和覆盖有什么不同?
虚函数总是在派生类中被改写,这种改写被称为”override“(覆盖)。
override是指派生类重写基类的虚函数。重写的函数必须有一致的参数表和返回值。
overload是”重载“,是指编写一个与已有函数同名但是参数表不同的函数。重载不是一种面向对象的编程,而只是一种语法规则,重载与多态没有什么直接关系。