类的派生:派生的意思,就是从一个已有类产生新类的过程。 类的继承,就是一个新的类从一个已有的类那里得到已有的特性。
已有的类称为父类或基类,新的类称为子类或派生类。
定义格式:
//单继承
class 新类名: 继承方式 基类
{
......
}
//多重继承
class 新类名: 继承方式 基类1, 继承方式 基类2,......,继承方式 基类n
{
......
}
类的继承让类和类之间有了层级关系,父类并不唯一,同时子类也不唯一,简单来说没什么限制。
继承方式:
- 公有继承public:父类中的共有成员(public),保护成员(protected)的访问在子类中属性不变,私有成员(private)不可直接访问.
- 私有继承private:父类中的共有和保护成员以私有成员身份出现,私有成员不可直接访问。
- 保护继承protected: 父类中的共有和保护成员以保护成员的身份出现,私有成员不可直接访问。
概括起来,就是:私有成员不可被继承,公有成员按继承方式改变成员身份,保护成员仅在私有继承中变为私有成员。
根据这个特点,有一点要知道:私有继承后,假设ClassSon私有继承了ClassFather,那么ClassFather的所有成员在ClassSon中就成了私有的成员,如果一个类ClassSon2要继承ClassSon,那么只能继承到ClassSon中的公有和保护成员,而ClassFather中的东西就跟ClassSon2没什么关系了。
这样可就看出了保护成员protected和私有成员private的差别:两者都是只能被类内部的函数访问,不能被类的实体对象访问,但是protected中的成员可以被继承,但是private中的成员不能被子类直接访问。
兼容规则:其实跟我们很多软件一样的,都是向上兼容,用子类可以代替父类做事,但是父类不能代替子类做事。但是注意子类只能使用从父类中继承来的东西。
派生类的构造函数:
(看完这部分我生生的觉得这是一个悲剧啊 囧rz)
跟普通的构造函数一样,要把基类继承来的成员和所有的数据成员初始化。语法形式为:
派生类名::派生类名(参数总表): 基类名1(参数表1), ... , 积累名n(参数表n), 内嵌对象名1(内嵌参表1), ... , 内嵌对象m(内嵌参表m){ 派生类新增成员的初始化语句; } |
看到这个我觉得大部分人都晕了,不管你晕不晕,反正我晕了,so,先来个短小的例子,然后根据例子,总结以下几点,就看得懂这个了:
class Son: public A, public B, public C{
public:
Son(int a, int b, int c, int d):A(a), sonB(d), sonA(b), B(c){}; // 位置(1)
private:
A sonA; // 位置(2)
B sonB; //
C sonC; //假设类C中的构造函数没有参数需要传递
}
// 引用时:
Son s(1,2,3,4);
- 注意位置1中,我特地打乱了A B sonA sonB 的位置,因为这个顺序并不重要,当然,顺序的话比较好看,还是建议跟总形参表中参数顺序相同。
- 在private中定义了sonC,但是假设C的构造函数并没有参数需要传递,那么可以在Son的构造函数中省略C和sonC。 Son的构造函数,在函数体前面初始化了ABC啥的,但是private中如果有新的成员,比如int之类的,还是要在函数体中初始化。
隐藏规则:
这么说吧,假如父类Father有一个数据成员int Time,一个共有函数成员int getTime(); 子类Son继承了类Father,并且在自己的类中又定义了一个数据成员int Time, 还很贱的又定义了一个函数成员int getTime(); 这种情况下,继承而来的那个Time和getTime()就被隐藏了。在引用的时候,如果只写了Time,那么说的其实是信定义的这个Time,只有写了Father::Time,指的才是继承来的这个Time。
虚基类:
就是虚父类啊我比较喜欢这种俗气的名字。
声明的语法方式: class 派生类名: virtual 继承方式 基类名1, 继承方式 基类名2
这里virtual只对基类名1起作用,基类名2并不是虚父类。
虚父类和父类的区别就是:如果共同基类是虚基类,从不同路径继承而来的同名数据成员在内存中只有一个拷贝,同一个函数名只也有一个映射。画个图表示:
这样应该比较清楚了 哎呦累死我了不写了