1. 用户和类的实现者
用户:指类的对象或实例。
类的实现者:包括类的成员。
2. private、public、protect成员
2.1派生类可以访问公有public成员,而不能访问私有private成员
2.2 protect成员
希望派生类分享但是不想被其他公共访问使用的成员。
- 可以看做是public和private中的产物。
- 受保护的成员对类的用户来说是不可访问的。
- 受保护的成员对于派生类的成员和友元来说是可访问的。
class Base{
protected:
int prot_mem; //protected 成员
};
class Sneaky:public Base{
friend void clobber(Sneaky&); //能访问Sneaky::prot_mem
friend void clobber(Base&); //不能访问Base::prot_mem
int j;
}
//正确能访问Sneaky对象的private和protected成员
void clobber(Sneaky& s) {
s.j=s.prot_mem=0;}
void clobber(Base& b){
b.prot_mem=0;}//错误不能访问protected的成员
3. 派生访问说明符
- 对于派生类的成员(及友元)能否访问其直接积累的成员没什么影响。eg. private 不影响派生类的访问权限,主要影响,相关函数的使用。
- 主要用来控制派生类用户对于基类成员的访问权限。比如struct Priv_Drev: private Base{}意味着在派生类Priv_Drev中,从Base继承而来的部分都是private的。
class Base2
{
friend class Pal;
public:
void pub_mem() {
}
protected:
int prot_mem;
private:
char priv_mem;
};
struct Pub_Derv : public Base2
{
int f() {
return prot_mem;}
};
struct Priv_Derv : private Base2
{
//私有继承不影响派生类中的访问,只是Base对于Priv_Derv来说都是private的
int f() const {
return prot_mem;}
};
void fun1()
{
Pub_Derv d1;
Priv_Derv d2;
d1.pub_mem();
// d2.pub_mem(); //error:这里是私有继承,用户不能调用private类型的
}
3.1 说明符可以控制继承自派生类的新类的访问权限
struct Derived_from_public : public Pub_Derv
{
int use_base() {
return prot_mem; } //ok:protected in pub_Derv
};
struct Derived_from_private : public Priv_Derv
{
int use_base(){
return prot_mem;} // error:这里prot_mem是private类型
};
3.2 派生类向基类转换的可访问性
假设D继承自B,
- 只有当D公有地继承B时,用户代码才能够使用派生类向基类的转换;如果D继承B的方式是保护的或者私有的,则用户代码不能使用该转换。
- 不论D以什么方式继承B,D的成员函数和友元都能使用派生类向基类的的转换;派生类向其会直接基类的类型转换对于派生类的成员和友元来说是永远可以访问的。
- 如果D继承B的方式是公有的或者受保护的,则D的派生类的成员和友元可以使用D向B的类型转换;反之,如果D继承B的方式是私有的,则不能使用
- 对于代码中的某个给定节点来说,如果基类的公有成员是可以访问的,则派生类向基类的类型转换也是可访问的;反之则不行。
4. 友元与继承
扫描二维码关注公众号,回复:
12667054 查看本文章
4.1 友元关系不能传递
如果windows_mgr有它自己的友元,那么这些友元并不一定具有访问Screen的特权。
class Screen{
friend class windows_mgr;
};
4.2. 友元关系不能继承(每个类负责控制各自成员的访问权限)
class Base{
friend class Pal;
protected:
int prot_mem; //protected 成员
};
class Sneaky:public Base{
friend void clobber(Sneaky&); //能访问Sneaky::prot_mem
friend void clobber(Base&); //不能访问Base::prot_mem
int j;
}
class Pal
{
public:
int f(Base2 b) {
return b.prot_mem;}
// int f2(Sneaky s) {return s.j;} error:Pal 不是Sneaky的友元
int f3(Sneaky2 s2) {
return s2.prot_mem;} //不要惊讶,这是对的
};
class D2 : public Pal
{
public:
// int mem(Base2 b){return b.prot_mem;} error: 友元是无法继承的!!!
};
5. using改变个别成员的可访问性
通过using声明可以改变派生类继承的某个名字的访问级别。
- private using 该名字能被类的成员和友元访问;
- public using 类的所有成员都能访问。
- protectde using 类的成员、友元和派生类是可访问的。
class Base {
public:
std::size_t size() const {
return n; }
protected:
std::size_t n;
};
class Derived : private Base {
public:
using Base::size; //保持对象尺寸相关的成员的访问级别
protected:
using Base::n; //使用using关键字改变成员变量的访问级别。
};
Derived d;
std::size_t t1 = d.size();//ok
std::size_t t2 = d.n;//error
6. 默认的继承保护级别
使用class关键字定义的派生类是私有继承的;使用struct关键字定义的派生类是公有继承的。
【引用】
[1] 代码oopTest.h