继承是C++中一个很好的特性,它能够从已有的类派生出新的类,而继承类继承了原有类(称为基类)的特征。继承类有三种,公有继承、保护继承、私有继承。
使用公有继承,基类的公有成员将成为继承类的公有成员,保护成员称为继承类的保护成员,基类的私有部分也将成为继承类的一部分,但只能通过基类的公有和保护方法来访问,但继承类不继承基类的构造函数、析构函数和赋值操作符。
使用保护继承,基类的公有成员和保护成员都将成为继承类的保护成员,由于基类的公有方法在第二代为保护成员,因此第三代继承类可以使用。
使用私有继承,基类的公有成员和保护成员都将成为继承类的私有成员,继承类不继承基类的接口。第三代继承类不能使用基类的接口。
| public | protected | private |
公有继承 | public | protected | 不可见 |
私有继承 | private | private | 不可见 |
保护继承 | protected | protected | 不可见 |
下面将通过几个例子来详细阐述这三者的区别:
第一个例子,继承类引用基类成员
1.引用基类公有成员和保护成员:
class A
{
protected:
void proA(){}
public:
A():iA(10){}
int iA;
void funA(){}
};
class B: public A
{
public:
void funB()
{
cout<<iA<<endl;
proA();
funA();
}
};
class C: protected A
{
public:
void funC()
{
cout<<iA<<endl;
proA();
funA();
}
};
class D: private A
{
public:
void funD()
{
cout<<iA<<endl; //直接调用
proA();
funA();
}
void funD2()
{
cout<<A::iA<<endl; //通过“基类名+::”调用
A::proA();
A::funA();
}
};
int main()
{
A a;
B b;
C c;
D d;
b.funB();
c.funC();
d.funD();
d.funD2();
return 0;
}
编译通过
结论1:不管是公有、保护还是私有继承,继承类都可以直接访问基类的公有成员及保护成员,可在继承类方法中直接调用或者通过“基类名+::”调用。static成员的引用在后面讨论。
2.引用基类私有成员
class A
{
int iA;
public:
A():iA(10){}
};
class B: public A
{
public:
void funB()
{
cout<<iA<<endl;
cout<<A::iA<<endl;
}
};
int main()
{
A a;
B b;
b.funB();
return 0;
}
编译出错
error C2248: “A::iA”: 无法访问 private 成员(在“A”类中声明)
结论2:公有、私有和保护继承都无法访问基类的私有成员,只能通过基类的公有成员和保护成员访问
第二个例子,继承类对象引用基类成员
1.公有继承:
class A
{
int priA;
protected:
void proA(){}
public:
A():priA(10),iA(10){}
int iA;
void funA(){}
};
class B: public A{};
int main()
{
A a;
B b;
cout<<b.priA<<endl; //公有继承无法引用基类私有数据
b.proA(); //公有继承无法引用基类保护方法
cout<<b.iA<<endl; //公有继承可以引用基类公有数据
b.funA(); //公有继承可以引用基类公有方法
return 0;
}
编译出错:
error C2248: “A::priA”: 无法访问 private 成员(在“A”类中声明)
error C2248: “A::proA”: 无法访问 protected 成员(在“A”类中声明)
结论3:公有继承的对象可以访问基类的公有成员,但无法访问基类的私有成员和保护成员
2、对于私有继承和保护继承
class A
{
int priA;
protected:
void proA(){}
public:
A():priA(10),iA(10){}
int iA;
void funA(){}
};
class C: protected A{};
class D: private A{};
int main()
{
A a;
C c;
D d;
cout<<c.iA<<endl;
c.funA();
cout<<d.iA<<endl;
d.funA();
system("pause");
return 0;
}
编译出错:
error C2247: “A::iA”不可访问,因为“C”使用“protected”从“A”继承
error C2247: “A::funA”不可访问,因为“C”使用“protected”从“A”继承
error C2247: “A::iA”不可访问,因为“D”使用“private”从“A”继承
error C2247: “A::funA”不可访问,因为“D”使用“private”从“A”继承
结论4:保护继承和私有继承的对象不能访问基类的公有、保护及私有成员
第三个例子,继承类和对象引用基类static成员
class A
{
public:
static int siA;
static void funA(){}
};
class B: public A{};
int A::siA=10;
int main()
{
B b;
cout<<B::siA<<endl;
B::funA();
cout<<b.siA<<endl;
b.funA();
return 0;
}
编译通过
*结论5:公有继承通过类或对象都可以访问基类的公有static成员,通过“类+::”调用或者“对象+.”调用。私有继承和保护继承的类可以访问基类公有static成员,但类对象不能访问。对于类中static成员的具体使用可参考C++类中static成员使用 *
第四个例子,第三代类
class A
{
protected:
void proA(){}
public:
void funA(){}
};
class B: public A{};
class BB: public B
{
public:
void funBB()
{
proA();
funA();
}
};
class C: protected A{};
class CC: protected C
{
public:
void funCC()
{
proA();
funA();
}
};
class D: private A{};
class DD: private D
{
public:
void funDD()
{
proA();
funA();
}
};
int main()
{
BB bb;
CC cc;
DD dd;
bb.funBB();
cc.funCC();
dd.funDD();
return 0;
}
编译出错
error C2248: “A::proA”: 无法访问 无法访问的 成员(在“A”类中声明)
error C2247: “A::funA”不可访问,因为“D”使用“private”从“A”继承
结论6:使用公有继承时,第三代类和对象都可以使用基类的公有方法;使用保护继承时,基类的公有方法在第二代为保护成员,因此第三代类可以使用,但第三类的对象不能使用;使用私有继承时,第三代类和对象将不能使用基类的所有方法。
总结:
- 公有、私有和保护继承都可以直接访问基类的公有成员以及保护成员
- 公有、私有和保护继承都无法直接访问基类的私有成员,只能通过基类的公有成员和保护成员访问
- 公有继承的对象可以访问基类的公有成员,但无法访问基类的私有成员和保护成员。私有继承和保护继承的对象不能直接访问基类的任何成员
- 公有继承的类或对象都可以访问基类的公有static成员。私有继承和保护继承的类可以访问基类公有static成员,但类对象不能访问。
- 使用公有继承时,第三代类和对象都可以使用基类的公有方法;使用保护继承时,基类的公有方法在第二代为保护成员,因此第三代类可以使用,但第三类的对象不能使用;使用私有继承时,第三代类和对象将不能使用基类的所有方法
PS: 码一篇文章还真TM累,走过路过的不要错过,留言增加点人气
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)