对继承的讨论
1. 继承的形式和继承的原理
class 派生类名:继承方式 基类名
{
成员声明;
};
上面是继承的形式。当继承发生后,可以认为派生类拥有了基类的成员。
例:
class A
{
public:
int i;
void show(){cout<
};
class B: public A
{
public:
int m;
void print(){cout<
};
void main()
{
B b;
b.m; b.i; b.show(); b.print();
}
这个例子就是继承的写法。其中类A是类B的父类,类B是类A的子类。可以认为类B拥有了类A的所有,也就是B中拥有了来自A的i和void show()函数。b.m; b.i; b.show(); b.print();都是对的。因为b是B类型的对象,所以b拥有了A和B的所有成员。
2. 关于继承方式(上面的红字部分)
继承方式有三种,分别是public,private,protected。
我们认为private为最严格的限制级别,认为protected为中等的限制级别,认为public为宽松的限制。
当继承发生时,我们可以认为父类的成员(无论成员函数还是数据成员)会迁移一份到子类。父类的成员也拥有访问的级别,这些级别也是由public,private,protected来说明的。如果继承,则父类中的成员迁移至子类。父类成员迁移至子类成员时,访问级别以父类和继承方式中更严的为准。
派生类对基类成员的使用,与继承访问控制和基类中成员性质有关
公有继承 基类的公有成员派生类的公有成员
基类的保护成员派生类的保护成员
私有继承 基类的公有成员和保护成员派生类的私有成员
保护继承 基类的公有成员和保护成员派生类的保护成员
公有继承
class A
{
private:
int m;
void print_private(){cout<<”private”<
protected:
int n;
void print_ protected (){cout<<” protected”<
public:
int q;
void print_ public (){cout<<” public”<
};
class B: public A
{
public:
int i;
void function(){………………………}
};
void main()
{
B b;
}
此时,类B拥有了类A的所有成员。并且这些成员在A中是什么形式,迁移到B中还是什么形式。也就是继承完之后B看上去就是如下的样子:
class B
{
private:
int m;
void print_private(){cout<<”private”<
protected:
int n;
void print_ protected (){cout<<” protected”<
public:
int q;
void print_ public (){cout<<” public”<
public:
int i;
void function(){………………………}
};
红色的成员可以视为B的成员,但这些成员来自于A的成员迁移。蓝色的代表迁移过程中访问性质变化。其中,一定要注意,B的对象b只能访问public下的成员,通过public下的成员函数可以访问protected下的成员,?? .但是,来自A的private成员必须用来自A的成员函数来访问。也就是function可以激活除去m和print_private()的剩下的所有内容,因为m和print_private()是A(也就是父类)的私有的成员。
保护继承
class A
{
private:
int m;
void print_private(){cout<<”private”<
protected:
int n;
void print_ protected (){cout<<” protected”<
public:
int q;
void print_ public (){cout<<” public”<
};
class B: protected A
{
public:
int i;
void function(){………………………}
};
void main()
{
B b;
}
此时,类B拥有了类A的所有成员。A成员迁移至B后,从前的限制级别比访问级别严格的或者相等的则不变,访问级别限制比protected宽松的则变为protected。也就是继承完之后B看上去就是如下的样子:
class B
{
private:
int m;
void print_private(){cout<<”private”<
protected:
int n;
void print_ protected (){cout<<” protected”<
protected:
int q;
void print_ public (){cout<<” public”<
public:
int i;
void function(){………………………}
};红色的成员可以视为B的成员,但这些成员来自于A的成员迁移。蓝色的代表迁移过程中访问性质变化。其中,一定要注意,B的对象b只能访问public下的成员,通过public下的成员函数可以访问protected下的成员,但是,来自A的private成员必须用来自A的成员函数来访问。也就是function可以激活除去m和print_private()的剩下的所有内容,因为m和print_private()是A(也就是父类)的私有的成员。
私有继承
class A
{
private:
int m;
void print_private(){cout<<”private”<
protected:
int n;
void print_ protected (){cout<<” protected”<
public:
int q;
void print_ public (){cout<<” public”<
};
class B: private A
{
public:
int i;
void function(){………………………}
};
void main()
{
B b;
}
此时,类B拥有了类A的所有成员。A成员迁移至B后,从前的限制级别比访问级别严格的或者相等的则不变,访问级别限制比private宽松的则变为private。也就是继承完之后B看上去就是如下的样子:
class B
{
private:
int m;
void print_private(){cout<<”private”<
private:
int n;
void print_ protected (){cout<<” protected”<
private:
int q;
void print_ public (){cout<<” public”<
public:
int i;
void function(){………………………}
};
红色的成员可以视为B的成员,但这些成员来自于A的成员迁移。蓝色的代表迁移过程中访问性质变化。其中,一定要注意,B的对象b只能访问public下的成员,通过public下的成员函数可以访问protected下的成员,但是,来自A的private成员必须用来自A的成员函数来访问。也就是function可以激活除去m和print_private()的剩下的所有内容,因为m和print_private()是A(也就是父类)的私有的成员。
3. 关于多层继承
class A
{
private:
int m;
void print_private(){cout<<”private”<
protected:
int n;
void print_ protected (){cout<<” protected”<
public:
int q;
void print_ public (){cout<<” public”<
};
class B: private A
{
public:
int i;
void function(){………………………}
};
class C: protected B
{
public:
int k;
void c_fun(){………………………}
};
多层继承只考虑相邻层。从上到下依次完成迁移过程。例如上例。继承完毕之后C如下:
class C
{
private:
int m;
void print_private(){cout<<”private”<
private:
int n;
void print_ protected (){cout<<” protected”<
private:
int q;
void print_ public (){cout<<” public”<
protected:
int i;
void function(){………………………}
public:
int k;
void c_fun(){………………………}
};
红色的成员和绿色的成员可以视为B的成员。蓝色的代表迁移过程中访问性质变化。其中,一定要注意,C的对象c只能访问public下的成员,通过public下的成员函数可以访问protected下的成员,但是,追根述源来自A本身的private成员必须用来自A的成员函数来访问。追根述源来自B本身的private成员必须用来自B的成员函数来访问。也就是c_fun可以激活除去红色部分的剩下的所有内容(即c_fun可以激活function()函数),function()函数可以激活print_ public ()和print_ protected (),print_ public ()和print_ protected ()又可以激活print_private()。
以后要注意一个问题:视为或者说拥有在继承中和访问是两回事。
4. 关于多继承
当一个子类继承多个父类时,相当于把父类一个一个的迁移至子类。这与多层继承是不同的。只存在一层继承。
class A
{
private:
int m;
void print_private(){cout<<”private”<
protected:
int n;
void print_ protected (){cout<<” protected”<
public:
int q;
void print_ public (){cout<<” public”<
};
class B:
{
public:
int i;
void function(){………………………}
};
class C: public A,protected B
{
public:
int k;
void c_fun(){………………………}
};
C可以看做
class C
{
private:
int m;
void print_private(){cout<<”private”<
protected:
int n;
void print_ protected (){cout<<” protected”<
public:
int q;
void print_ public (){cout<<” public”<
protected:// protected??????
int i;
void function(){………………………}
public:
int k;
void c_fun(){………………………}
};
继承发生时,C受A,B独立的控制,也就是A和B的内容都独立的按照自己的规则进入C。
对比:多层继承和多继承
我们先看一个例子,本文档第5页第3大标题中的例子。
这个例子中,B继承自A,C继承自B,也就是A的成员虽然最终迁移至了C,但是,C获得的A成员的性质受到了B的影响。
¥29.8
¥9.9
¥59.8