第15章 面向对象程序设计
1. 构造基类和派生类。
其中A类是基类,B类是派生类。派生类的构造函数必须重新写过,不能继承。(因为毕竟两个类的类名都不一样,不可能构造函数继承)只继承其他的成员函数和成员变量。
派生类可以覆盖基类的虚函数,但是也可以选择不覆盖(即直接使用父类的函数版本)比例A类的print_1()虚函数就没有被覆盖。
基类的静态成员:如果基类有一个静态成员,那么基类和所有派生类都共同拥有这仅有的一个静态成员。
2. 基类的虚函数默认实参最好与派生类的虚函数默认实参一致。
因为如果通过基类的引用或指针调用函数,则将使用基类的默认实参版本,但是该函数的实现是动态绑定的,即可能是基类的函数也可能是派生类的函数。
3. 派生类可以改变基类中成员的访问权限。
但是仅限于那些派生类可访问的基类成员。
使用using声明即可。
4. 派生类中与基类的同名成员将隐藏基类的该成员。
5. 在当前派生类中可以访问当前派生类的基类的protected成员,但是不可以访问别的基类或派生类的成员。
6. 除了重新定义虚函数外,派生类的成员一定不要和基类的成员同名。且一定要在派生类重新定义的虚函数前面加上virtual关键字(就算你不加,C++也默认该函数为虚函数,但是为了用该派生类的”客户”看的清晰,一定要加上)
如果基类有虚函数 virtual void p(); 的话,那么派生类如果定义一个函数void p(); 由于该函数与基类的虚函数同名且调用形式相同,所以void p()也是虚函数。强烈建议在派生类void p()前中加上virtual关键字。
如果派生类中的函数是 void p(int x=1); 这样的话,那么这个p函数不是虚函数且掩盖了基类的虚函数名p()。
我们依次分析上述4个调用:
首先是第一个pa->p(),此时pa=&b。因为pa是一个A类指针,所以编译器在类A中寻找p函数,但是它发现p函数是一个virtual的,所以动态绑定后调用的是B类的 virtual p()函数,但是B类的virtual p()使用的是A类的默认实现,所以这里最终调用的还是A::p()函数。
第二个pa->p()类似于第一个,也是虚函数调用,pa绑定的是&a,所以调用的是A::p()这个虚函数。
第三个b.p(),由于b是一个对象,所以p函数静态绑定,所以调用的是b::p(int x=1) 这个函数。
第四个a.p(),静态绑定,调用a::p()函数。
7. 用于多态的基类的析构函数一定要是虚函数。
因为如果基类的析构函数不是virtual的,delete 一个基类指针只会调用基类的析构函数,不会调用子类的析构函数(就算该指针是子类的指针).
原文地址:http://blog.csdn.net/u013480600/article/details/44171077