C++ 访问控制与继承


C++的三大特性之一——封装:隐藏对象的属性和实现细节,仅对外公开接口和对象进行交互,将数据和操作数据的方法进行有机结合。主要通过访问限定符:public/private/protected实现。

三种访问权限

public限定符

被public限定符所修饰的成员变量和函数可以被类的函数、子类的函数和对象、友元函数,也可以由类的对象来访问,即可以使用成员运算符(.或->)来访问。这里的友元函数,可以是该类的友元函数,也可以是该类的友元类的成员函数。

private限定符

被private限定符修饰的成员只能被该类的函数和友元函数访问,子类函数和对象无法访问,在这三个限定符中封装程度是最高的,一般来说,应该尽可能将类的成员变量声明为private而不是其他,减少成员变量的暴露,只提供getter和settter方法给外界访问,这样能提高类的安全性。

protected限定符

protected限定符修饰的成员变量和成员函数可以被 该类及其派生类 的成员函数和友元访问,但是不能被类对象(无论是基类还是派生类)所访问,即不能通过类对象的成员运算符(.或->)来访问。

继承与访问

某个类对其继承而来的成员的访间权限受到两个因素影响:一是在基类中该成员的访问说明符,二是在派生类的派生列表中的访问说明符。

派生访问说明符对于派生类的成员(及友元)能否访问其直接基类的成员没有影响。对基类成员的访问权限只与基类中的访问说明符有关:

class Base{
public:
    void pub_mem();
protected:
    int prot_mem;
private:
    char priv_mem;
};
struct Pub_Derv: public Base{
    //正确:派生类能访问protected成员
    int f() { return prot_mem; }
    //错误:private成员对于派生类来说不可访问
    char g() { return priv_mem; }
};
struct Priv_Derv : private Base{
    //private不影响派生类的访问权限
    int f1() const { return prot_mem; }
}

派生访问说明符的目的是控制派生类对象(包括派生类的派生类在内)对于基类成员的访问权限:

Pub_Derv d1;    //继承自Base的成员是public的
Priv_Derv d2;   //继承自Base的成员是private的
d1.pub_mem();   //正确:pub_mem在派生类中是public的
d2.pub_mem();   //错误:pub_mem在派生类中是private的

派生访问说明符还可以控制继承自派生类的新类的访问权限:

struct Derived_from_Public : public Pub_Derv{
    //正确:Base::prot_mem在Pub_Derv中仍然是protected的
    int use_base() { return prot_mem; }
};
struct Derived_from_Private : public Priv_Derv{
    //错误:Base::prot_mem在Priv_Derv中是private的
    int use_base() { return prot_mem; }
};
struct Derived_from_Protected : protected Pub_Derv{
    //正确:Base::prot_mem在Pub_Derv中仍然是protected的
    int use_base() { return prot_mem; }
};
Derived_from_Public dfp;
dfp.pub_mem();		//正确
Derived_from_Protected dfpr;
dfpr.pub_mem();		//错误,Base的所有成员在派生类中是受保护的

公有、私有、受保护继承 相当于 将基类中的成员 加上对应访问权限放入派生类中:

  • 若继承方式是public,基类成员在派生类中的访问权限保持不变,也就是说,基类中的成员访问权限,在派生类中仍然保持原来的访问权限;

  • 若继承方式是private,基类所有成员在派生类中的访问权限都会变为私有(private)权限;

  • 若继承方式是protected,基类的公有成员和保护成员在派生类中的访问权限都会变为保护(protected)权限,私有成员在派生类中的访问权限仍然是私有(private)权限。

在这里插入图片描述

友元与继承

就像友元关系不能传递一样(参见7.3.4节,第250页),友元关系同样也不能继承。

基类的友元在访问派生类成员时不具有特殊性,类似的,派生类的友元也不能随意访问基类的成员。

改变个别成员的可访问性

有时我们需要改变派生类继承的某个名字的访问级别,通过使用using声明可以达到这一目的:

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

因为Derived使用了私有继承,所以继承而来的成员size和n(在默认情况下)是Derived的私有成员。然而,我们使用using声明语句改变了这些成员的可访问性。改变之后,Derived的用户将可以使用size成员,而Derived的派生类将能使用n。

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


public继承与多态

只有当public继承时,才会展现多态,因为public继承意味“is-a”的关系:
如果你令class D以public继承class B,你便是告诉编译器:

  • 每一个类型为D的对象同时也是一个类型为B的对象,编译器可以自动将class D转换为class B。反之不是
  • B对象可使用的地方,D对象一样可以使用。反之不是

private继承

因为private继承的派生类对象无法被转换为基类对象,所以不能展现多态。

  • private继承 意味implemented-in-terms-of(根据某物实现出) 。
    如果你让class D以private形式继承class B,你的用意是为了采用class B内已经备妥的某些特性,不是因为B对象和D对象存在有任何观念上的关系。
  • private继承意味只有实现部分被继承,接口部分应略去

implemented-in-terms-of也可以由复合实现。在应用域,复合意味着has-a;在实现域,复合意味着is-implemented-in-terms-of。尽可能使用复合实现这种关系,必要时(涉及protected成员或virtual函数时)才使用private继承。

参考:《Effective C++》条款 39:明智而审慎地使用private继承

final关键字

C++11的关键字final有两个用途:

  • 放在类后阻止该类被继承;
  • 放在虚函数后阻止该虚函数被覆盖。

参考:
https://www.cnblogs.com/chenwx-jay/p/9649108.html
https://blog.csdn.net/casky237/article/details/54766881
《C++primer 第五版》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值