C++ 类访问控制public/private/protected探讨

摘要:本文是从饮水思源BBS C/C++版上一篇帖子引发的思考。当时看到帖子,突然觉得平时见惯了的,在这里似乎变得陌生了,究竟访问控制符怎样起作用,怎样使用,该怎样理解,本文试图给出讨论。

原帖如下
 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指针传入这个参数。于是就完成了对象与成员函数的绑定(或联系).
实例化后就得到同一个类的多个不同的对象,既然成员函数共享的,那么成员函数就可以操作对象的数据成员。
问题是现在有多个对象,成员函数需要知道操作的是哪个对象的数据成员?
比如有对象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语言中的结构体可以一边定义一边用吗?

#define NULL 0
struct student
{
 long num;
 float score;
 struct  student  *next;     就是这里student结构体还没有定义完怎么可以直接用?是什么效果?
};
main()
{ 
 struct student a, b, c,   *head,    *p;
   a.num=99101; 
   a.score=89.5;
   b. num=99103; 
   b.score=90;
   c.num=99107 ; 
   c.score=85;
    head=&a;     
 a.next=&b;            
 b.next=&c;      
 c.next=NULL;
    p=head;  
  do
 {  
  printf("%ld %5.1f\n",p->num,p->score);
      p=p->next;   
}
 while(p!=NULL);  
}
你写的就是一个超简单的单向链表么。

肯定没有问题的,结构体本来就有嵌套一说。就是结构体内可以嵌套结构体。嵌套自己也是嵌套么。

 struct  student  *next;就是定义一个指针,指向的类型就是struct student这种类型。你后来不也把这个next指向了下一个结构体指针么。

再细说下吧。
struct student
{
 long num;
 float score;
 struct  student  *next;     就是这里student结构体还没有定义完怎么可以直接用?是什么效果?
};

这个就是说,你定义了一个结构体类型,就是struct student,和int、char都是一个意思,可以用来定义一个变量,也就是结构体变量。
只不过,定义的这个结构体变量中,又有好多个其他类型的变量。这些变量里,可以有int、char等,也可以有其他类型的结构体,当然,也可以有自己类型的结构体。
评论(2) | 0 0
2013-11-30 15:36zjfaok   | 十三级
哪怕还没有声明struct student,也照样可以使用struct  student  *next;因为编译器完全可以识别出这是指向结构体的指针,但是只有定义了结构体student之后,才可以进行解引用操作如*next,即next的用处是极度受限的。不过只要struct student的定义完成(遇到对应的右大括号),这样的限制也就消失,在后面的代码中完全可以正常的使用……
评论 | 0 0
2013-11-30 15:21Bug丶达仔 | 三级

正如楼上所说,C中结构体是可以嵌套使用的。简单理解,编译器在程序头遇见了

1
2
3
struct student
{
};

就会默默的告诉自己,现在除了int啊,float啊,又多了一个生命,哦不,声明叫struct student,然后编译器再去看括号内的东西

1
2
3
long num;
float score;
struct  student  *next;

前两个不用多说了,是long型和float型,编译器都认得,突然看见了struct  student  *next;然后编译器想起来是刚刚多的一个小伙伴。

1
struct  student  *next;

是一个指针类型,指向struct  student  。


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。