玩命加载中 . . .

15.4-访问控制与继承


访问控制与继承

class Base {
protected:
    int prot_mem;
};

class Sneaky : public Base {
    friend void clobber(Sneaky&);   // 能访问Sneaky::prot_mem
    friend void clobber(Base&);     // 不能访问Base::prot_mem
    int j;
};

void clobber(Sneaky &s) {
    s.j = s.prot_mem = 0;   // 正确
}

void clobber(Base &b) {
    b.prot_mem = 0;     // 错误
}

友元函数可以访问Sneaky的所有成员,所以访问私有的j和受保护的prot_mem都没问题
但是它不是Base的友元,所有不能访问Base的受保护成员

某个类对其继承而来的成员的访问权限受到两个因素的影响:

  • 在基类中该成员的访问说明符
  • 在派生类的派生列表中的访问说明符

两者取权限较小的

class Base {
public:
    void pub_mem();
protected:
    int prot_mem;
private:
    char priv_mem;
};

struct Pub_Derv : public Base {
    int f() { return prot_mem; }    // 正确
    int g() { return priv_mem; }    // 错误
};

struct Priv_Derv : private Base {
    int f1() { return prot_mem; }   // 正确
};

Pub_Derv类中有从Base继承而来的publicpub_mem成员,还有protectedprot_mem成员,但是没有privatepriv_mem成员

Priv_Derv类中有从Base继承而来的privatepub_mem,还有privatepriv_mem,在类内可以访问

Pub_Derv d1;
Priv_Derv d2;
d1.pub_mem();   // 正确
d2.pub_mem();   // 错误,不能访问private成员
  • 派生访问说明符的目的是控制派生类用户对于基类成员的访问权限
  • 派生访问说明符还可以控制继承派生类的新类的访问权限
struct Derived_from_Public : public Pub_Derv {
    int use_base() { return prot_mem; } // protected
};

struct Derived_from_Private : public Priv_Derv {
    int use_base() { return prot_mem; } // 错误,不能继承基类的private成员
};

public权限

  • 用户可以访问
  • 类内部,继承类和友元函数可以访问

protected权限

  • 用户不能访问
  • 类内部,继承类和友元函数可以访问

private权限

  • 用户不能访问
  • 继承类不能访问
  • 类内部和友元函数可以访问

友元与继承:友元不能继承

class Base {
    friend class Pal;
protected:
    int prot_mem;
};

class Pal {
public:
    int f(Base b) { return b.prot_mem; }    // 正确,友元可以访问所有类的成员
    int f2(Sneaky s) { return s.j; }    // 错误,友元不能访问派生类的私有成员
    int f3(Sneaky s) { return s.prot_mem; }     // 正确,友元可以访问派生类的基类部分
};

Pal能够访问Base的成员,这种访问包括了Base对象内嵌在其派生类对象中的情况

对基类的访问权限由基类本身控制,即使对于派生类的基类部分也是如此

class D2 : public Pal {
public:
    int mem(Base b) { return b.prot_mem; }  // 错误,友元不能继承
};

可以使用using改变个别成员的可访问性

class Base {
public:
    size_t size() const { return n; }
protected:
    size_t n;
};
class Derived : private Base {  // private继承
public:
    using Base::size;
protected:
    using Base::n;
};

相当于修改了原本的访问说明符,私有继承之后本来都是private,修改为publicprotected

派生类只能为那些它可以访问的名字提供using声明

默认的继承保护级别

class Base {};
struct D1 : Base {};    // 默认public继承
class D2 : Base {};     // 默认private继承

文章作者: kunpeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kunpeng !
  目录