c++ public private protect

http://blog.chinaunix.net/u1/41167/showart_1084013.html

原帖如下


[1 #include

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<\
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指针传入这个参数。于是就完成了对象与成员函数的绑定(或联系).

实例化后就得到同一个类的多个不同的对象,既然成员函数共享的,那么成员函数就可以操作对象的数据成员。

问题是现在有多个对象,成员函数需要知道操作的是哪个对象的数据成员?

比如有对象obj1和obj2,都属于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就可以更清晰的看出:





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



通俗的讲,同类的对象间可以“互相访问”对方的数据成员,只不过访问途径不是直接访问.

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



C++中public,protected,private访问小结

第一:private,public,protected方法的访问范围.(public继承下)

private: 只能由该类中的函数、其友元函数访问,不能被任何其他访问,该类的对象也不能访问.

protected: 可以被该类中的函数、子类的函数、以及其友元函数访问,但不能被该类的对象访问

public: 可以被该类中的函数、子类的函数、其友元函数访问,也可以由该类的对象访问

注:友元函数包括两种:设为友元的全局函数,设为友元类中的成员函数



第二:类的继承后方法属性变化:

使用private继承,父类的所有方法在子类中变为private;

使用protected继承,父类的protected和public方法在子类中变为protected,private方法不变;

使用public继承,父类中的方法属性不发生改变;


public: protected: private:
public继承 public protected ---
protected继承 protected protected ---
private继承 private private ---


protected继承和private继承能降低访问权限



再次提到:可以提供访问行为的主语为“函数”。

类体内的访问没有访问限制一说,即private函数可以访问public/protected/private成员函数或数据成员,同理,protected函数,public函数也可以任意访问该类体中定义的成员

public继承下,基类中的public和protected成员继承为该子类的public和protected成员(成员函数或数据成员),然后访问仍然按类内的无限制访问





对于类域范围内,成员函数访问无所谓访问限制。

对于继承情况下的基类private成员,在派生类中仍然继承了下来,只不过它不能直接访问, 即使在类里也不行, 更不用说是类对象了。

可以通过下列例子看到:


1#include<iostream>

2
usingnamespace std;

3

4
class C{

5public:

6C(int val) : m_c(val) {}

7private:

8int m_c;

9};

10

11
classD:public C{

12public:

13D(intval1,int val2) : C(val1), m_d(val2) {}

14int m_d;

15};

16

17
int main()

18{

19

20


21
cout<<sizeof(C)<<""<<sizeof(D)<<endl;//4 8

22
D obj(2,25);

23cout<<&obj<<""<<&obj.m_d<<endl;//0x0012FF78 0X0012FF7C

24//cout << obj.m_c;//error, 不能访问

25


26
D*ptr=&obj;

27int*iptr=(int*)ptr;

28cout<<*iptr<<""<<*(iptr+1)<<endl;//2 25

29


30return0;

31}

32

33



同样,加入虚函数,可以看到VC编译器将vptr放置在数据区的最开头



](http://blog.chinaunix.net/u1/41167/showart_1084013.html)
下面这个问题摘自论坛的一个帖子
[
已知3个类O、P和Q,类O中定义了一个私有方法F1、一个公有方法F2和一个受保护的方法F3:类P和类Q是类O的派生类,其继承方式如下所示:

class P : protected O {…};

class Q : public O {…};

关于方法F1的描述中正确的是(34);关于方法F2韵描述中正确的是(35);关于方法F3的描述中正确的是(36)

(34)

A.方法F1无法被访问

B.只有在类O内才能访问方法F1

C.只有在类P内才能访问方法F1

D.只有在类Q内才能访问方法F1

(35)

A.类O、P和Q的对象都可以访问方法F2

B.类P和Q的对象都可以访问方法F2

C.类0和Q的对象都可以访问方法F2

D.只有在类P内才能访问方法F2

(36)A.类0、P和Q的对象都可以访问方法F3

B.类0、P和Q的对象都不可以访问方法F3

C.类0和Q的对象都可以访问方法F3

D.类P和Q的对象都可以访问方法F3。

有甚么办法可以简单地记住这许多的规则? 下文告诉你一个根本不需要记的办法。

顾名思义,private/public/protected 分别表示 私有/公开/保护,它们是一组用于访问权限控制的关键字。那么首先,需要澄清的一个关键点是,是要控制谁访问谁的权限?这个访问的主语(施事)是谁?宾语(受事)是谁?

我们经常听到这样的说法:

1)一个类友元可以访问该类的任何成员(包括成员变量及成员方法,下同)。

2)private成员只有该类自身可以访问,protected成员只有该类及其派生类可以访问,public成员所有的人都可以访问。

宾语(受事)是谁这一点很明确,是类的成员(包括成员变量及成员方法)。主语(施事)是谁?这是让大家发生混淆的关键点。也是这个说法中含糊不清的地方。

想清楚一点,其实主语(施事)指的是一个函数,而不是类(当然更不是变量)。private/public/protected要控制的是一个函数(施事)对一个类的成员(包括成员变量及成员方法)的访问权限。因此比较完整的说法是:

1)一个类友元(包含友元函数或者友元类的所有成员函数)可以访问该类的任何成员(包括成员变量及成员方法)。

2)除去友元外,private成员只有该类自身的成员函数可以访问,protected成员只有该类的成员函数及其派生类的成员函数可以访问,public成员则所有的函数都可以访问。

也就是说,当我们说一个类可以访问XXX,其实暗指这个类的成员函数可以访问XXX。了解了这一点,外加一条显而易见的规则,上面的问题就不难回答了。这条规则是:

3)派生类在继承时可削弱成员的访问权限(通过protected/private修饰)。例如上面的例子class P : protected O {…}; 那么某个函数通过类P访问O中成员时,该函数对类O中的public成员只有protected权限。

补充:有一种技术叫Member Spy(类成员间谍),通过该技术派生类可将基类的protected成员修改为public权限。这种技术用到了using关键字。举例如下:

class A

{

protected:

int m_data;

};

class SpyA : public A

{

public:

using A::m_data;

};



void TestSpy(A pA)

{

SpyA
pSpyA = static_cast(pA);

// 强制转换A为SpyA,这要求SpyA没有成员变量且没有重载A中的虚函数。

// 现在你可以通过pSpyA访问m_data了。例如:int data = pSpyA->m_data;

}

由于这种技术用到了强制类型转换,当谨慎使用。

naunix.net/u1/41167/showart_1084013.html](http://blog.chinaunix.net/u1/41167/showart_1084013.html)原文链接: https://www.cnblogs.com/edward259/archive/2010/03/19/1689879.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/8934

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月6日 下午8:17
下一篇 2023年2月6日 下午8:20

相关推荐