近日写游戏时,发现引擎中的一个菜单不能实现自己需要的功能,所以对其扩展,继承,但有个父类中私有成员,派生类需要访问,在代码中出现一系列问题。今日复习下继承。
一、公有(Pulic)继承
“继承”是类的重要特性。A类继承B类,我们称B类为“基类”,也称为“父类”,A类则相应地被称为“派生类”或“子类”。A类继承了B类之后,A类就具有了B类的部分成员。那么,究竟从基类那儿得到了哪些成员,这由2方面决定,①继承方式,②基类成员的访问权限(即public/private/protected)。
继承有三种方式,即公有(Public)继承、私有(Private)继承、保护(Protected)继承。我们先讨论最常用的公有继承。公有继承就是将基类的公有成员变为自己的公有成员,基类的保护成员变为自己的保护成员。
#include
<iostream>#include
<string>using namespace
std;class
CBase { string name;int
age;public
: string getName() {return
name; }int
getAge() {return
age; }protected
:void
setName(string s) { name = s; }void
setAge(int
i) { age = i; } };class
CDerive :public
CBase { //用“public”指定公有继承public
:void
setBase(string s,int
i) { setName(s); //调用基类的保护成员 setAge(i); //调用基类的保护成员 //调用基类的私有成员 //cout << name <<" " << age << endl; //编译出错 } };int
main ( ) { CDerive d; d.setBase("abc", 100); //调用基类的私有成员 //cout << d.name <<" " << d.age << endl; //编译出错 //调用基类的公有成员 cout << d.getName() <<" " << d.getAge() << endl; //调用基类的保护成员 //d.setName("xyz"); //编译出错 //d.setAge(20); //编译出错return
0; }
从上面的例子可以看出,对于公有继承,基类的成员能否访问,有以下特征:
- 基类的私有成员:在派生类和外部都不可以访问。
- 基类的公有成员:在派生类和外部都可以访问。
- 基类的保护成员:在派生类可以访问,在外部不可以访问。
二、私有(Private)继承
私有继承是将基类的公有成员和保护成员变成自己的私有成员,而基类的私有成员在派生类里本身就不能访问。
#include
<iostream>#include
<string>using namespace
std;class
CBase { string name;int
age;public
: string getName() {return
name; }int
getAge() {return
age; }protected
:void
setName(string s) { name = s; }void
setAge(int
i) { age = i; } };class
CDerive :private
CBase { //用“private”指定私有继承,private可以省略public
:void
setBase(string s,int
i) { setName(s); //调用基类的保护成员 setAge(i); //调用基类的保护成员 //调用基类的私有成员 //cout << name <<" " << age << endl; //编译出错 } string getBaseName() {return
getName(); //调用基类的公有成员 }int
getBaseAge() {return
getAge(); //调用基类的公有成员 } };int
main ( ) { CDerive d; d.setBase("abc", 100); //调用基类的私有成员 //cout << d.name <<" " << d.age << endl; //编译出错 //调用基类的公有成员 //cout << d.getName() <<" " << d.getAge() << endl; //编译出错 cout << d.getBaseName() <<" " << d.getBaseAge() << endl; //调用基类的保护成员 //d.setName("xyz"); //编译出错 //d.setAge(20); //编译出错return
0; }
从上面的例子可以看出,对于私有继承,基类的成员能否访问,有以下特征:
- 基类的私有成员:在派生类和外部都不可以访问。
- 基类的公有成员:在派生类可以访问,在外部不可以访问。
- 基类的保护成员:在派生类可以访问,在外部不可以访问。
三、保护(Protected)继承
保护继承是将基类的公有成员和保护成员变成自己的保护成员,而基类的私有成员在派生类里本身就不能访问。
#include
<iostream>#include
<string>using namespace
std;class
CBase { string name;int
age;public
: string getName() {return
name; }int
getAge() {return
age; }protected
:void
setName(string s) { name = s; }void
setAge(int
i) { age = i; } };class
CDerive :protected
CBase { //用“private”指定私有继承public
:void
setBase(string s,int
i) { setName(s); //调用基类的保护成员 setAge(i); //调用基类的保护成员 //调用基类的私有成员 //cout << name <<" " << age << endl; //编译出错 } string getBaseName() {return
getName(); //调用基类的公有成员 }int
getBaseAge() {return
getAge(); //调用基类的公有成员 } };int
main ( ) { CDerive d; d.setBase("abc", 100); //调用基类的私有成员 //cout << d.name <<" " << d.age << endl; //编译出错 //调用基类的公有成员 //cout << d.getName() <<" " << d.getAge() << endl; //编译出错 cout << d.getBaseName() <<" " << d.getBaseAge() << endl; //调用基类的保护成员 //d.setName("xyz"); //编译出错 //d.setAge(20); //编译出错return
0; }
从上面的例子可以看出,对于私有继承,基类的成员能否访问,有以下特征:
- 基类的私有成员:在派生类和外部都不可以访问。
- 基类的公有成员:在派生类可以访问,在外部不可以访问。
- 基类的保护成员:在派生类可以访问,在外部不可以访问。
四、三种继承方式的比较
从上面的结果来看,私有继承和保护继承作用完全一样。仔细一想其实还是有区别,区别是如果派生类再一次去派生其它类时,对于刚才的私有继承来说,再派生的类将得不到任何成员。而对于刚才的保护继承,仍能够得到基类的公有和保护成员。
A类(基类) | B类(A的派生类) | C类(B的派生类) | |
---|---|---|---|
公有继承 | 公有成员 | 公有成员 | 公有成员 |
私有成员 | (无) | (无) | |
保护成员 | 保护成员 | 保护成员 | |
私有继承 | 公有成员 | 私有成员 | (无) |
私有成员 | (无) | (无) | |
保护成员 | 私有成员 | (无) | |
保护继承 | 公有成员 | 保护成员 | 保护成员 |
私有成员 | (无) | (无) | |
保护成员 | 保护成员 | 保护成员 |