找回密码
 FreeOZ用户注册
查看: 1915|回复: 15
打印 上一主题 下一主题

[论坛技术] 问一个c++菜鸟问题。。

[复制链接]
跳转到指定楼层
1#
发表于 13-9-2009 23:46:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?FreeOZ用户注册

x
最近看到一个例子,一个matrix类:
class matrix {
public:
//constructor
//destructor
matrix & operator = (const matrix &);
...
private:
int **im;
int rows;
int cols;
...
}

然后这个copy assignment是这样写的:
matrix &matrix:perator = (const matrix &rhs)
{
  if (this != &rhs) {
    if (rows != rhs.rows || cols != rhs.cols) {
      matrix::~matrix();
      //init something
    }
    initMatrix(rhs.im);//init matrix
  }
  return *this;
}

手工敲的,累,就不全部敲出来了。。。我想问的是在这个函数里面,rhs.rows和rhs.cols能这样直接访问?rows和cols不是private的么?
回复  

使用道具 举报

2#
发表于 13-9-2009 23:51:03 | 只看该作者

回复 #1 dflovely 的帖子

一家人,就不要太见外了

评分

参与人数 1威望 +20 收起 理由
dflovely + 20 谢谢分享!

查看全部评分

回复  

使用道具 举报

3#
 楼主| 发表于 14-9-2009 09:53:11 | 只看该作者

回复 #2 coredump 的帖子

是么?
在这个copy assignment的实现里,rhs不是另外一个实例么,总觉得怎么能直接访问一个实例的私有成员呢?
回复  

使用道具 举报

4#
发表于 14-9-2009 11:22:11 | 只看该作者
访问控制是针对类的,不是针对实例的

评分

参与人数 1威望 +20 收起 理由
dflovely + 20 谢谢分享!

查看全部评分

回复  

使用道具 举报

5#
发表于 14-9-2009 13:01:10 | 只看该作者
LS正解。

评分

参与人数 1威望 +20 收起 理由
dflovely + 20 谢谢分享!

查看全部评分

回复  

使用道具 举报

6#
 楼主| 发表于 14-9-2009 14:44:48 | 只看该作者
这么说,一个类的成员函数可以访问这个类的任何一个实例的私有成员?
回复  

使用道具 举报

7#
发表于 14-9-2009 15:17:59 | 只看该作者

yes.

you can have a class like this to test:

void CTest::TestPrivate(CTest& test)
{       
        test.m_Private = 1;
        int i = test.m_Private;

        CTest test2;
        test2.m_Private = 2;
        int j = test.m_Private;
}

评分

参与人数 1威望 +10 收起 理由
dflovely + 10 10分感谢!

查看全部评分

回复  

使用道具 举报

8#
发表于 14-9-2009 17:27:34 | 只看该作者
你这个不是重载引用的实现吗?还没有声明实例,也没有对实例的私有成员进行访问哪?所以也不会产生编译器的保护。
回复  

使用道具 举报

9#
发表于 14-9-2009 17:29:29 | 只看该作者
原帖由 dflovely 于 14-9-2009 14:44 发表
这么说,一个类的成员函数可以访问这个类的任何一个实例的私有成员?

这当然了,自己的成员函数不能都访问,那私有成员变量给谁用呀?不就是给自己用的吗。
回复  

使用道具 举报

10#
发表于 15-9-2009 00:45:47 | 只看该作者
以前还真不知道可以这样。
回复  

使用道具 举报

11#
发表于 18-9-2009 16:09:49 | 只看该作者
原帖由 dflovely 于 14-9-2009 09:53 发表
是么?
在这个copy assignment的实现里,rhs不是另外一个实例么,总觉得怎么能直接访问一个实例的私有成员呢?


嘿嘿,偶第一次看到这个玩意的哦时候,也是吓了一跳,怎么访问了人家的private变量了

实验下来就是没问题,细细想想,所谓的类私有成员的保护是基于类级别的,一个类的无数个实例是共享一份成员函数的。所谓的保护机制,其实就是成员函数能够得到类成员变量在内存中相对类起始位置的偏移量而已。要绕过这层保护,你设计一个成员函数,返回私有成员的偏移量。其他的类或者函数应该能够通过这个偏移量直接去访问该私有变量的。
回复  

使用道具 举报

12#
发表于 18-9-2009 18:28:32 | 只看该作者
哪怕一个类的多个实例是共享一份成员函数,但是不应该是共享同一个私有变量。多个实例的同一个成员函数也许是指向内存同一个地方,但是多个实例的同名的私有变量应该是在内存中有多个地址的。从道理上还是有点想不通,虽然现实确实如此。

就好比如果中国人是一个类,那所有的中国人都可以掏其他中国人的口袋,这个私有的“口袋”只是对其他类(其他国家的人)私有,而不是对其他实例私有。没有真正学过面向对象的理论,不知道这种特点是特意设计的,还是。。。
回复  

使用道具 举报

13#
发表于 18-9-2009 18:43:40 | 只看该作者
happy好空啊
回复  

使用道具 举报

14#
发表于 19-9-2009 20:55:33 | 只看该作者
原帖由 someonehappy 于 18-9-2009 18:28 发表
哪怕一个类的多个实例是共享一份成员函数,但是不应该是共享同一个私有变量。多个实例的同一个成员函数也许是指向内存同一个地方,但是多个实例的同名的私有变量应该是在内存中有多个地址的。从道理上还是有点想不通 ...


我私下认为是为了实现起来方便而这么做的,因为既然成员函数已经具有了该类所有变量的相对位移,想要限制该函数对成员变量进行访问就是很麻烦的事情,要不断的比较this指针和类实例指针,看看是否是对自己的实例进行的访问。
回复  

使用道具 举报

15#
发表于 22-9-2009 18:20:37 | 只看该作者
其实,楼主是误解了面向对象中“封装”对程序员的意义。

封装,不是为了安全性。要知道,编译器去对程序员作安全防范是荒谬的事情。程序员是电脑的上帝,理论上只要他有足够的知识,他应该可以编程完成任何任务,所有的安全防范对他来说都是毫无作用的。
所以,C++以及所有面向对象语言的封装功能并不是为了把字段锁起来不让访问,而是相反,使得对这个字段的访问更容易控制。

比如说,如果你写了一个1000000行的C++,然后发现了一个问题。在追踪的过程中,你发现对某个字段的错误访问是问题的根源。但是grep的结果显示对该字段的访问有10000处。那么你该怎么办呢?
如果该字段是公有的,那就很棘手。但如果该字段是私有的,那么你就知道其它类对它的访问必然是通过访问函数进行。而如果该类的代码不是很多,那么只要处理一下类内部的访问就可以了。这就简化了后续的追踪过程。

如果你理解以上这些,就会明白,封装级别到“对象”一级意义其实不大。因为把封装限制在类级别,已经足够把对私有成员的访问限制在类和它的友员函数内部。假设封装级别到了“对象”一级,对很多常用类功能的实现都会造成很大限制(比如,比较两个类对象是否相等需要访问两个类实例的相应字段),而限制访问的粒度其实增加不大。
回复  

使用道具 举报

16#
发表于 22-9-2009 19:03:55 | 只看该作者
原帖由 someonehappy 于 18-9-2009 18:28 发表
哪怕一个类的多个实例是共享一份成员函数,但是不应该是共享同一个私有变量。多个实例的同一个成员函数也许是指向内存同一个地方,但是多个实例的同名的私有变量应该是在内存中有多个地址的。从道理上还是有点想不通,虽然现实确实如此。
同一个C++的多个对象实例可不是共享同一个成员变量的啊,除非这个变量是静态的。 事实就是你说的:”多个实例的同名的私有变量是在内存中有多个地址的“。



private/public/protected 这些关键字,只是访问修饰符,它们不能改变对象的内存分布状态,一个类的所有成员都是private,和同样的类,但是把private改成public,其对象实例在内存中是100%一致的。这些访问修饰符所起的作用只体现在编译期间,如果你在类的前面用#define private public这样的小把戏调戏一把C++编译器就知道了。同样的,const修饰符也是仅作用于编译期。


但是像static这类关键字就不同了,一个对象成员是否有static修饰,其对象实例的内存二进制布局是完全不同的。



《C++对象模型》这本书专门有好几章来讲解C++对象的内存分布。
回复  

使用道具 举报

您需要登录后才可以回帖 登录 | FreeOZ用户注册

本版积分规则

小黑屋|手机版|Archiver|FreeOZ论坛

GMT+10, 9-5-2024 04:36 , Processed in 0.026935 second(s), 32 queries , Gzip On, Redis On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表