今天学习的主要内容是类的继承与派生,需要重要注意的是protected的作用,需要明确的是如果没有类的继承与派生,protected和private的作用是一样的,在这种情况下,可以认为protected private 是一样的,都不允许类对象之外的操作对数据进行读取,现在讨论在类的继承与派生中protected的作用,类的派生有两种,一是公有派生,二是私有派生。不管何种派生,基类中的私有成员都是不能访问的,基类中的公有成员都是可以访问的,关键的区别就在与protected,在公有派生中,基类的protected部分在派生类中仍然保持protected属性,而在私有派生中,基类的protected部分在派生类中就会变成私有部分。上边叙述了类的继承与派生的基本知识,派生类会继承基类的所有的公有成员和保护成员,而派生的意思就是原来基类的基础上派生出新的数据单元和类的方法。
关于虚函数,这是自己认为在c++学习当中一个比较难以理解的内容,因为虚函数的概念在c语言中是没有出现,和函数的重载一样,c++中多态目前自己见到就有函数的重载和虚函数,而虚函数又分为普通虚函数和纯虚函数。在什么时候会用到虚函数?
刚开始学习虚函数,需要明确的是虚函数于再有继承关系的父类与子类之间或者说基类与派生类之间,在c++中,每一个类对象都有一个虚函数表,记录类对象的函数以及继承重载相关的函数列表。类的继承需要的做的工作首先是复制基类的虚函数表,它把这个虚函数表放在自己虚函数的头部,然后顺次放入自己的虚函数表,这样,派生类的虚函数表除了自己的虚函数信息外,还有了基类的虚函数表信息。我们考虑下,如果基类和派生类都有一个返回值、函数名相同的函数,就出现了对象成员的重载,而派生会出现两个虚函数表,分别记录基类与派生类的虚函数。写个程序验证下,编译器会怎么处理这种情况。
#include <iostream.h> class animal { public: int age; virtual void disp(void){cout<<"age="<<age<<endl;}//重载 animal(int i){age=i; } }; class person:public animal { public: char sex; virtual void disp(void){cout<<"sex="<<sex<<endl;}//重载 person(int i,char ch):animal(i){sex=ch; } }; void disp(animal &a) { a.disp(); } int main(void) { person king(12,'m'); disp(king); return 0;
}
执行结果:sex=m 可见执行了派生类中的disp()函数.
|
现在可以这么来理解,在基类和派生类如果出现虚函数,那么编译器编译后,会在内存中对象的内存区开一虚函数表存储区,这里存储了基类和派生类的虚函数,如果出现虚函数的重载情况,派生类会将基类的虚函数覆盖掉。也就是派生的虚函数信息覆盖了基类的虚函数信息,那么在通过基类引用的方式就可以了访问派生类的虚函数了。
这里在考虑下,如果不使用虚函数,而在基类和派生类中出现函数重载,如果调用该函数,执行的会是那个?这个问题还是比较好考虑的,首先,编译器的优先原则,派生类继承基类,那么在内存中,基类的信息放在内存中对象的靠前的部分,同理,派生类的信息放在靠后的部分,这样如果你调用函数时,在参数 一样的前情况,当然会有限执行基类的函数。(有待考证)
在说下纯虚函数,纯虚函数是一个比较容易理解的概念,首先在派生类继承基类后,如果在基类中申明某一函数为纯虚函数,格式为:
virtual void example(void)=0;
|
那这函数就是纯虚函数,纯虚函数只在基类中申明,而定义部分需要在派生类中完成,而这总只在基类中申明纯虚函数的类称之为抽象类,带有纯虚函数的类称为抽象类,抽象类是不能定义对象的,在实际中为了强调一个类是抽象类,可将该类的构造函数说明为保护的控制权限,抽象类只能作为基类来使用,其纯虚函数的实现有派生类给出。如果派生类中没有重定义纯虚函数,则这个派生类仍然还是一个抽象类。
阅读(1498) | 评论(1) | 转发(0) |