之前学习过程中,知道了对于保护成员,公有继承后还是保护的,私有继承后就变成私有成员了。但我突然想到对于类中的方法呢?后来做了一系列实验,并查找了一些资料,把这部分彻底搞懂了。
有很多例子是讲类的成员变量的,比如基类Base中有protected成员a,那么私有继承后,如 class child : private Base,在child中,a已经变成了private了,如果是保护继承a还是protected。那么对于Base中的public成员,在私有继承时变成了private,了,在保护继承就变成了protected了。
对于成员变量的总结如下:基类中的protected或public成员变量,在protected继承后就一最低权限为主,protected的为protected,public的变为protected;在private继承后,protected的成员变量为private,public的成员变量也都变为private了,对于public继承,则维持不变。
这样的改变又有什么用呢?其实就是在下一个子类中的访问权限被改变了,通过这种继承,可以限制类的子类对类的父类的访问权限。
同时我想那么成员变量是如此,成员函数呢?
下面的例子是我用来实验的代码。
using namespace std;
class Base
... {
public:
Base(int i): a(i) ...{ cout<<"Base Created"<<endl; }
~Base() ...{}
int geta() ...{ return a; }
protected:
void Base_print() ...{ cout<<"Base Print"<<endl; }
private:
int a;
} ;
class Child1 : public Base
... {
public:
Child1(int i):Base(i), b(i) ...{ cout<<"Child1 Created"<<endl; }
~Child1() ...{}
void print() ...{ Base_print(); }
void print_a() ...{ cout<<geta()<<endl; }
private:
int b;
} ;
class Child2 : private Base
... {
public:
Child2(int i):Base(i), b(i) ...{ cout<<"Child2 Created"<<endl; }
~Child2() ...{}
void print() ...{ Base_print(); }
void print_a() ...{ cout<<geta()<<endl; }
private:
int b;
} ;
class Child3 : public Child2
... {
public:
Child3(int i) : Child2(i), b(i) ...{ cout<<"Child3 Created"<<endl; }
~Child3() ...{};
void print_all()
...{
//Base_print();
//cout<<Base::geta()<<endl;
cout<<b<<endl;
}
private:
int b;
} ;
int main( int argc, char ** argv)
... {
Child1 c1(1);
Child2 c2(2);
Child3 c3(3);
c1.print();
c1.print_a();
c2.print();
c2.print_a();
c3.print_all();
return 0;
}
可能这个例子代表性不够,还需要点改进,但也够说明问题了,从这个例子来看,从Base类继承了两个类:一个public的Child1,一个private的Child2,这两个类中的方法差不多,都是访问Base类中的protected方法Base_print()和public方法geta(),同时在main中调用各个类的方法,来查看输出,而Child3类从Child2继承过来,调用了基类中geta(),同时有个注释掉的Base_print(),如果取消Base_print()的注释,那么编译报错,说明私有继承类Child2屏蔽了Base_print()的访问权限,而对于geta(),如果前面不加Base:: ,编译报的错误就会是无法访问,而如果Child3从Child1继承而来,就不会出现这些问题,可见私有继承屏蔽了不少权限。(今天又试了一次,发现有点问题,私有继承的类,它的子类无法再访问Base的所有成员。谢谢janet的回复,所有修改了一下这个文章,也不知道之前是怎么试出来的)
如果Child2为保护继承类,也不会出现问题。
从以上来看,成员函数和成员变量都一样。
同时,在main中注释掉的调用可以看出,对于实例化的对象,无法访问自己的保护方法。
我的实验结论就是这样,不知道是否正确。下面是我总结个表格。
| Base | Drived | D_Drived |
public 继承 | public | public | public |
protected | protected | protected | |
private | 无法访问 | 无法访问 | |
protected | public | protected | protected |
protected | Protected | Protected | |
private | 无法访问 | 无法访问 | |
private | public | private | 无法访问 |
protected | private | 无法访问 | |
private | 无法访问 | 无法访问 |