抽空总结下对一直以来对C++多态性的一点个人理解:
1.什么叫早绑定和晚绑定?
早绑定指在对象声明的时候就和它的类型建立了关联。
晚绑定是指代码在运行时再检查对象是否提供了我们所需要的方法和属性。
静态关联(早绑定)和动态关联(晚绑定)。
2.什么叫多态性?
一个接口,多种方法。
3.多态性和非多态性的区别?
多态与非多态的实质区别就是函数地址是早绑定还是晚绑定。如果函数的调用,在编译器编译期间就可以确定函数的调用地址,并产生代码,是静态的,就是说地址是早绑定的。而如果函数调用的地址需要在运行时才确定,这就属于晚绑定。
4.一个不带虚函数的类(无成员变量)大小?
空类大小不为0,为1。
5.一个带虚函数的类(无成员变量)大小?
其对象会产生一个虚函数表,,相当于多了一个指针型的成员变量,在有成员变量时也同样要考虑,比如含一个char型成员变量,带一个或几个(多少个也只有一个虚表)虚成员函数,都相当于含一个char, 一个指针,sizeof()大小为8。
6.能不能在构造函数中调用虚函数?
在构造函数中调用虚函数时,采用早绑定,也就是虚函数机制在构造函数中不工作。
在C++构造函数中,虚函数调用会被编译器自动转为普通函数调用。
7.为什么构造函数不能为虚函数?
1. 编译器在构造对象时,必须知道确切的类型,才能正确的生成对象,因此不能采用晚绑定。
2. 由虚函数机制可以知道,在构造函数执行前,对象中的虚函数表指针并没有正确的初始化,无法使用虚函数表来调用构造函数。
3. 在C++中,一个类如果有多个构造函数,构造函数不能调用其他的构造函数。
8.纯虚函数和虚函数区别?
纯虚函数就是只声明了有这种函数 但不会给出这个函数的内容 所以任何继承了这个函数的子类的成员函数都必须定义这个函数的内容,如
果不定义,则子类也是抽象类,无法生成对象。
虚函数 声明了有这种函数 而且给除了这个函数的内容 任何继承了这个函数的子类成员函数 如果本身没有定义这个函数的内容 就采用基类
的这个函数 如果子类重新定义了了这个函数 那么通过基类的指针就能过根据对象来判断选择哪个函数 。
9.虚函数怎么定义?
只需要在声明前加virtual,不需要在定义时加,一旦基类的某个函数成为虚函数,子类对应的函数不需要加virtual,也会自动成为虚函数,
当然子类的子类对应的函数也会自动成为虚函数。
10.下面重点理解虚函数:
[cpp] view plaincopyprint?- class A
- {
- public:
- virtual void Say() ;
- virtual~A(){cout<<"~A"<<endl;}
- };
- void A::Say(){cout<<"A Say"<<endl;};
- class B:public A
- {
- public:
- void Say(void);
- ~B(){cout<<"~B"<<endl;}
- };
- void B::Say(void){cout<<"B Say"<<endl;}
- int _tmain(int argc, _TCHAR* argv[])
- {
- A *p = new B ;
- p->Say() ;
- delete p;
- system("pause") ;
- return 0 ;
- }
1.虚函数的作用是晚绑定,如上例,A *p = new B ;p->Say() ;如果Say()是虚函数,则会在运行时动态选择合适的对象Say(),如果不是虚函数,则只会选择A的Say(),要明白一点,如果不是动态链接的,如B b;b.Say();,这是静态的,编译器在编译就知道应该调用B的Say(),那么是不是虚函数都无所谓的,
2.析构函数最好声明为虚函数,这是针对new对象来说的,如上例,A *p = new B ,如果不用delete p;,那么A和B的析构函数肯定都不会被调用,如果用了delete p,但析构函数不是虚函数,则只会调用A的析构函数,不会调用B的析构函数,这其实和2是同一道理,如果析构函数是虚函数,则调用B的析构函数再调用A的析构函数。
3.无论析构函数是不是虚函数,如果用B b这种静态声明,都会先调用B的析构函数再调用A的析构函数
转载于:https://www.cnblogs.com/sjlove/p/3168593.html