访问控制

访问控制

访问控制
派生类继承了基类的全部数据成员和除了构造函数、析构函数之外的全部函数成员,
但是这些成员在派生类今的访问属性在派生过程中是可以调整的,继承方式控制了基类中
具有1i同访问属性的成员在派生类中的访问属性。
基类的成员可以有publicprotectedprivate3种访问属性,基类的自身成员可以对基
类中任何一个其他成员进行访问,但是通过基类的对象就只能访问这类的公有成员。
类的继承方式有publicprotectdprivate 3种。不同的继承方式会导致原来具有不同
访问属性的基类成员在派生类中的访问属性也有所不同。这里说的访问主要来自两个方面:
一是派生类中的新增成员对从基类继承来的成员的访问;二是在派生类外部通过派生类的
对象对从基类继承来的成员的访问。下面分别说明这3种继承方式。

1、公有继承
当类的继承方式为公有继承时,基类publicprotected成员的访问属性在派生类中保持
原来的访问属性不变,而基类private成员在派生类中不可访问。即基类的publicpretected
成员分别作为派生类的publicpretected成员,派生类的其他成员可以直接访问它们。其他
外部使用者只能通过派生类的对象访问继承来的pubuc成员,而无论是派生类的成员还是派
生类的对象都无法访问基类的private成员。

2、私有继承

当类的继承方式为私有继承时,基类publicprotected成员都以private成员属性出现在
派生类中,而基类private成员在派生类中不可访问。即基类的pubicprotected成员被继承
后作为派生类的私有成员,派生类的其他成员可以直接访问它们,但是在类外部通过派生
类的对象无法访问它们。无论是派生类的成员还是派生类的对象,都无法访问从基类继承
private成员。
经过私有继承之后,所有基类的成员都成为派生类的私有成员,如果进一步派生的话,
基类的成员就无法在新的派生类中被访问。因此,私有继承之后,基类的成员再也无法在
以后的派生类中发挥作用,实际是相当于中让了基类功能的继续派生。

3

当类的继承方式为保护继承时,基类public比和protected成员都以private成员身份出现
在派生类中,而基类private成员不可访问。即基类的publicprotected成员被继承以后作为
派生类的保护成员,这样,派生类的其他成员就可以直接访问它们,但在类外部通过派生
类的对象无法访问。无论是派生类的成员还是派生类的对象,都无法访问基类的private
员。
比较私有继承和保护继承可以看出,在直接派生类中,所有成员的访问属性都是完全
相同的。但是,如果派生类作为新的基类,那么当继续派生时,二者的区别就出现了。
假设B类以私有方式继承A类后,B类又派生出C类,那么C类的成员和对象都不能访
问间接从A类中继承来的成员。如果B类是以保护方式继承了A类,那么A类中的公有和保
护成员在B类中部是保护成员。B类在派生出C类后,A类中的公有和保护成员被C类间接继
承后,有可能是保护的或者是私有的(视从BC的派生方式不同而异)。因而,C类的成
员有可能可以访问间接从A类中继承来的成员。

注意:C++的访问修饰符的作用是以类为单位,而不是以对象为单位。

通俗的讲,同类的对象间可以互相访问对方的数据成员,只不过访问途径不是直接访问.
步骤是:通过一个对象调用其public成员函数,此成员函数可以访问到自己的或者同类其他对象的public/private/protected数据成员和成员函数(类的所有对象共用),而且还需要指明是哪个对象的数据成员(调用函数的对象自己的成员不用指明,因为有this指针;其他对象的数据成员可以通过引用或指针间接指明)

看下面的例子

1 #include<IOSTREAM>
2 using namespace std;
3
4 class A{
5 public:
6 A(int i_,int j_)
7 {
8 i=i_;
9 j=j_;
10 }
11 void disp(A &a)
12 {
13 cout<<a.i<<endl<<a.j<<endl;//
注意这里对象的访问
14 }
15
16 private:
17 int i;
18 protected:
19 int j;
20 };
21
22 int main(int argc, char* argv[])
23 {
24 A a(123,456);
25 A b(789,543);
26 a.disp(b);
27 b.disp(a);
28
29 return 0;
30 }

 

初看起来,倒是会产生疑问。为什么会这样,是否有bug
仔细考究起来,我们其实可以这样看待类和对象:
类是将数据成员和进行于其上的一系列操作(成员函数)封装在一起,注意:成员函数可以操作数据成员(可以称类中的数据成员为泛数据成员)!
对象是类的实例化,怎样理解实例化?其实每一个实例对象都只是对其中的数据成员初始化,内存映像中每个对象仅仅保留属于自己的那份数据成员副本。而成员函数对于整个类而言却是共享的,即一个类只保留一份成员函数。
那么每个对象怎样和这些可以认为是分离的成员函数发生联系,即成员函数如何操作对象的数据成员?记住this指针,无论对象通过(.)操作或者(->)操作调用成员函数,编译时刻,编译器都会将这种调用转换成我们常见的全局函数的形式,并且多出一个参数(一般这个参数放在第一个),然后将this指针传入这个参数。于是就完成了对象与成员函数的绑定(或联系).
实例化后就得到同一个类的多个不同的对象,既然成员函数共享的,那么成员函数就可以操作对象的数据成员。
问题是现在有多个对象,成员函数需要知道操作的是哪个对象的数据成员?
比如有对象obj1obj2,都属于A类,A类有public成员函数foo()
如果obj1调用该函数,编译时会给foo函数传入this指针,obj1,foo中操作obj1自身的成员就不用任何修饰,直接访问,因为其中的数据成员自动根据this指针找到。
如果obj1调用该函数,同样可以访问同类的其他对象的数据成员!那么你需要做的是让foo函数知道是同类对象中哪个对象的数据成员,一个解决办法是传入同类其他对象的指针或引用,那么就可以操作同类其他对象的数据成员。
foo(A &obj)
这样定义,然后调用:
obj1.foo(obj2)
就可以在obj1访问obj2的数据成员,而无论这些数据成员是private还是protected

搬出C++ Object Model,可以画出各个对象的内存map就可以更清晰的看出:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值