public/protected/private简介

#include <IOSTREAM>

using namespace std;

class A{

public:

A(int i_,int j_)

{

i=i_;

j=j_;

}

void disp(A &a)

{

cout<<a.i<<endl<<a.j<<endl;

}

private:

int i;

protected:

int j;

};

int main(int argc, char* argv[])

{

A a(123,456);

A b(789,543);

a.disp(b);

b.disp(a);

return 0;

}

初看起来,倒是会产生疑问。为什么会这样,是否有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++的访问修饰符的作用是以类为单位,而不是以对象为单位。

通俗的讲,同类的对象间可以“互相访问”对方的数据成员,只不过访问途径不是直接访问。步骤是:通过一个对象调用其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成员,在派生类中仍然继承了下来,只不过它不能直接访问,即使在类里也不行,更不用说是类对象了。

可以通过下列例子看到:

#include <iostream>

using namespace std;

class C{

public:

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

private:

int m_c;

};

class D: public C{

public:

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

int m_d;

};

int main()

{

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

D obj(2, 25);

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

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

D *ptr = &obj;

int *iptr = (int *)ptr;

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

return 0;

}

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

下面这个问题摘自论坛的一个帖子:

已知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 : protectedO {…};那么某个函数通过类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<SpyA*>(pA);

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

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

}

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

public/protected/private简介相关推荐

  1. JAVA修饰符类型(public,protected,private,friendly)

    JAVA修饰符类型(public,protected,private,friendly) public的类.类属变量及方法,包内及包外的不论什么类均能够訪问: protected的类.类属变量及方法, ...

  2. Java关键字系列(public,protected,private)

    Java关键字系列(public,protected,private) public.protected和private做为java访问权限修饰词而使用. 首先要明白,java中的每个定义(定义类.字 ...

  3. C++ 类访问控制(public/protected/private)小结

    第一:private, public, protected 访问标号的访问范围. private:只能由1.该类中的函数.2.其友元函数访问. 不能被任何其他访问,该类的对象也不能访问. protec ...

  4. php protected 的继承,14 PHP 类的继承 [public protected private] parent 构造方法 析构方法 重写 最终类和方法 设计模式...

    类的继承 简单理解: 某个类A具有某些特征,另一个类B,也具有A类的所有特征,并且还可能具有自己的更多的一些特征,此时,我们就可以实现:B类使用A的特征信息并继续添加自己的一些特有特征信息. 基本概念 ...

  5. C++ (public, protected, private继承)

    http://thinkinginmylife.spaces.live.com/blog/cns!E44140D5E07BEC07!137.entry 我转~~~C++5(public, protec ...

  6. C++ 类访问控制(public/protected/private)

    From: http://cnmtjp.blog.51cto.com/204390/36548 C++中 public,protected, private 访问标号小结 第一:private, pu ...

  7. C++:C++中public protected private关键字用法

    C++:C++中public protected private关键字用法 笔者这里主要针对C++中public protected private关键字做一个较全面的总结.首先public prot ...

  8. C++类中的访问权限问题---public/protected/private

    派生类继承了基类的全部数据成员和除了构造.析构函数之外的全部成员函数,但是这些成员的访问属性在派生的过程中通过继承方式可以来调整. 第一:private,public,protected方法的访问范围 ...

  9. object-c的存取权限(public/protected/private)

    和C++,Java等面向对象编程语言一样,object-c中对于数据成员可以设定它们的访问权限,它规定了外部实体如何来访问这些资源.例如: 1. 代码: //Access.h #import < ...

最新文章

  1. 会计的思考(20):还原会计报表的企业个性之四(持续经营)
  2. zend studio配置调试(Xdebug方式)
  3. python电脑下载什么软件好-Python工具 | 4个好用的开源 Python 下载器
  4. Java 编程的动态性 第1 部分: 类和类装入--转载
  5. Struts2与Struts1的对比
  6. html5基础知识点字体属性
  7. os.walk() 遍历目录下的文件夹和文件
  8. 手机搜狗浏览器怎么样
  9. 【算法分析与设计】浅析二分查找
  10. hdu 1709 母函数变形
  11. Codeforce432 Prime Swaps
  12. ADODB.Recordset 错误 '800a0e7d' 的解决方法
  13. 《数字货币与人民币国际化》读书笔记2
  14. 什么目录存放Linux源代码,Linux根目录下有哪些目录,存放的内容是什么?
  15. 四种常见的颜色模式及各自的特点?
  16. IEEE 802.2 LLC协议
  17. php 鼠标 移动 手型,JS实现的鼠标跟随代码(卡通手型点击效果)
  18. python爬虫进阶案例,Python进阶(二十)-Python爬虫实例讲解
  19. Ubuntu 16.04升级Openssh7.8p1
  20. html下拉菜单换背景颜色,如何在select框下拉菜单中更改蓝色突出显示的颜色

热门文章

  1. 绝命毒师口语精析(3)
  2. 对Spring框架的理解(转)
  3. Xcode8 报 ”xx“is missing from working copy 的问题解决方法
  4. 【原】NIO通信模型和BIO通信模型
  5. Geotools之“Hello World”——打开本地shp文件并显示
  6. 服务框架HSF分析之一容器启动
  7. C#代码生成目录树(转)
  8. 在线常用crontab表达式大全验证解析
  9. mysql5.5免安装包_mysql免安装版5.5
  10. P1280 尼克的任务