同一个类的两个不同对象可以访问对方的private成员吗?

softworm 2003-08-25 03:33:35
请大家看看下面这段程序,它是能够正常编译连接运行的。但是为什么
assign成员函数没有错呢?谁能告诉我c++中关于这种情况的内幕?谢谢!

#include <stdio.h>

class Test {
private:
int a;
int b;
public:
Test(int a_v, int b_v);
void assign(Test *source);
void print(void);
};

Test::Test(int a_v, int b_v)
{
a = a_v;
b = b_v;
}

void Test::assign(Test *source)
{
a = source->a;
b = source->b;
}

void Test::print()
{
printf("a = %d, b = %d\n", a, b);
}

int main()
{
Test t1(1, 2), t2(3, 4);

t2.assign(&t1);

t2.print();

return 0;
}
...全文
511 41 打赏 收藏 转发到动态 举报
写回复
用AI写文章
41 条回复
切换为时间正序
请发表友善的回复…
发表回复
softworm 2003-09-20
  • 打赏
  • 举报
回复
谢谢各位的热心发言。在此我准备结贴了。
TianGuangZao 2003-09-12
  • 打赏
  • 举报
回复
对楼主的疑问简单回答。
在定义一个类时,你可以把其它类对象作为该类的数据成员,也可以让该类的成员函数接受其它类对象,这里的其它类包括自己。
hfhappyfish 2003-09-12
  • 打赏
  • 举报
回复
C++正是通过访问控制来实现封装和数据的隐藏
它通过关键字private,public,等关键字和类的定义来达到访问控制的的目的。
但这不是唯一目的
hfhappyfish 2003-09-12
  • 打赏
  • 举报
回复
把C++看作更好的C
也可以这样理解
struct Test{
int a;
int b;
};
void Test::assign(Test *this,Test *source)
{
this->a = source->a;
this->b = source->b;
}
而C++在此基础上使用了
private关键字和使assign出现在类的成员中
---------------------------------------------------------------------
private关键字告诉编译器结构a,b只能被类的成员函数(或者友元)访问;
assign出现在类成员中告诉编译器它是类Test的成员,有权限访问任何一个实例化结构的a与b。
所以编译器不认为有错。
这体现了C++的缺陷?
hfhappyfish 2003-09-12
  • 打赏
  • 举报
回复
因为t2.assign(&t2);是正确的
t2.assign(&t1);与上面没有本质区别
step_by_step 2003-09-11
  • 打赏
  • 举报
回复
因为c++的封装性只到类这一层,不到对象这一层,所以那个assign函数没有什么好奇怪的
鄢老 2003-09-11
  • 打赏
  • 举报
回复
我运行了一下,结果是a=1,b=2.后来想了想,觉得是很正常的。因为t1和t2是在同一个类成员函数中定义,之后又在同一个类成员函数中运算的,所以说t1的私有成员可以当成参数传给t2的私有成员的。
l1ul1u 2003-09-09
  • 打赏
  • 举报
回复
c++是可以这样访问的
xueweizhong 2003-09-08
  • 打赏
  • 举报
回复
贴上去就格式乱了,再贴一下:

再论ACCESS-CONTROL:
(我把搂主的代码简化了一下下)

/**
* 请大家看看下面这段程序,它是能够正常编译连接运行的。但是为什么
* assign成员函数没有错呢?谁能告诉我c++中关于这种情况的内幕?谢谢!
*/

#include <stdio.h>

class Test
{
private:
int a;
public:
Test(int);
void assign(Test const* source);
};

void Test::assign(Test *source)
{
a = source->a;
}

int main()
{
Test t1(1), t2(2);
t2.assign(&t1);
}

1: 关于ACCESS-CONTROL的定义

<<C++98 std/chapter 11>>:
1 A member of a class can be

--private; that is, its name can be used only by
member functions, static data members, and
friends of the class in which it is declared.

--protected; that is, its name can be used only by
member functions, static data members, and
friends of the class in which it is declared
and by member functions, static data members,
and friends of classes derived from this class.

--public; that is, its name can be used
anywhere without access restriction.

2: 一些相关的note:
1) name
ACCESS-CONTROL 只应用到name(simple identifier).
按照上面的定义,ACCESS-CONTROL针对且只针对
member of class.
即使是涉及到模板,也只是关心name,
而不关心template-argument

2) unnamed object
无名对象不考虑access-control:
如下:
struct A
{
private:
struct B
{
int i;
};
B m_b;
public:
B& f() { return m_b; }
};
int main()
{
A a;
f()->i; // only names are f, i,
// f and i is public,
// so it's legal even
// if B in private A member
}
3) 关于protected member name有一个例外情况,
参见(4:)中例子的new note

3: 让人迷惑的代码段的注记

void Test::assign(Test *source)
{
a = source->a;
/**
1) 这里出现的name是
void, Test, assign, source, a
2) void, Test, source,
不是class member,
不做access-control考虑
3) assign是成员函数名,
但我们只是定义它,
不在这里使用,
也不做access-control考虑

4)a是private Test member,
可以在A的成员函数中使用,
现在刚好是在Test的
assign成员函数体内。

5) but what about "source->a":
OK, a in "source->a" means
a is a member name of source's class Test
and used in Test member function,
everything is fine!!!
(still confusing, see following example ...)
*/
}

4: 更加清楚的例子(我的)注记

struct Base
{
protected:
int m_protected;
};

struct Son2 : Base {};

struct Son1 : Base
{

void foo(Son1& s)
{
s.m_protected; // legal, Son1可以
// 看到所有自己子类的秘密。
/**
new note:
same as 3/5)
*/
}

void foo(Base& b)
{
b.m_protected; // illegal <--
// 比如Son1不能看到Son2的东西
//(b may be a Son2)
// Son1不能看到兄弟Son2的秘密。
/**
new note:
m_protected in "b.m_protected" means:
m_protected is Base(b's type) class
member, not Son1 class member
which means:
Base's protected member is used
in Son1's member function
By definition, it's legal, but
因为C++标准规定一个关于
proected member的例外情况,
When a member function of a
derived class references
a protected nonstatic member
of a base class, an access check
applies in addition to those
described earlier in this clause:
Except when forming a pointer to
member,the access must be through
a pointer to,
reference to,
<---我们的情况
or object
<---下一个成员函数的情况
of the derived class itself
(or any class derived from that class).
因为儿子不能管老子,所以结论是
illegal
*/

}
void foo(Base b)
{
b.m_protected; // seems legal. why??
/**
new note:
illegal : 儿子不能管老子
原因同 void foo(Base& c)的分析。
*/
}
};
supwjhuLoveCjj 2003-09-08
  • 打赏
  • 举报
回复
C++的封装是针对类的,而不是针对对象的
已经足够说明问题了
xueweizhong 2003-09-08
  • 打赏
  • 举报
回复
再论ACCESS-CONTROL:
(我把搂主的代码简化了一下下)

/**
* 请大家看看下面这段程序,它是能够正常编译连接运行的。但是为什么
* assign成员函数没有错呢?谁能告诉我c++中关于这种情况的内幕?谢谢!
*/

#include <stdio.h>

class Test
{
private:
int a;
public:
Test(int);
void assign(Test const* source);
};

void Test::assign(Test *source)
{
a = source->a;
}

int main()
{
Test t1(1), t2(2);
t2.assign(&t1);
}

1: 关于ACCESS-CONTROL的定义

<<C++98 std/chapter 11>>:
1 A member of a class can be

--private; that is, its name can be used only by member functions,
static data members, and friends of the class in which it is
declared.

--protected; that is, its name can be used only by member functions,
static data members, and friends of the class in which it is
declared and by member functions, static data members, and friends
of classes derived from this class (see _class.protected_).

--public; that is, its name can be used anywhere without access
restriction.

2: 一些相关的note:
1) name
ACCESS-CONTROL 只应用到name(simple identifier).
按照上面的定义,ACCESS-CONTROL针对且只针对 member of class.
即使是涉及到模板,也只是关心name, 而不关心template-argument
2) unnamed object
无名对象不考虑access-control:
如下:
struct A
{
private:
struct B
{
int i;
};
B m_b;
public:
B& f() { return m_b; }
};
int main()
{
A a;
f()->i; // only names are f, i, f and i is public, so it's legal even if B in private A member
}
3) 关于protected member name有一个例外情况,参见(4:)中例子的new note

3: 让人迷惑的代码段的注记

void Test::assign(Test *source)
{
a = source->a;
/**
1) 这里出现的name是void, Test, assign, source, a
2) void, Test, source, 不是class member, 不做access-control考虑
3) assign是成员函数名, 但我们只是定义它,不在这里使用,也不做access-control考虑

4)a是private Test member, 可以在A的成员函数中使用,现在刚好是在Test的assign成员函数体内。

5) but what about "source->a":
OK, a in "source->a" means a is a member name of source's class Test
and used in Test member function,
everything is fine!!!
(still confusing, see following example ...)
*/
}

4: 更加清楚的例子(我的)注记

struct Base
{
protected:
int m_protected;
};

struct Son2 : Base {};

struct Son1 : Base
{

void foo(Son1& s)
{
s.m_protected; // legal, Son1可以看到所有自己子类的秘密。
/**
new note:
same as 3/5)
*/
}

void foo(Base& b)
{
b.m_protected; // illegal <--比如Son1不能看到Son2的东西(b may be a Son2)
// Son1不能看到兄弟Son2的秘密。
/**
new note:
m_protected in "b.m_protected" means:
m_protected is Base(b's type) class member, not Son1 class member
which means:
Base's protected member is used in Son1's member function
By definition, it's legal, but
因为C++标准规定一个关于proected member的例外情况,
When a member function of a derived class
references a protected nonstatic member of a base class,
an access check applies in addition to those described
earlier in this clause:
Except when forming a pointer to member,the access must be through
a pointer to,
reference to, <---我们的情况
or object <---下一个成员函数的情况
of the derived class itself (or any class derived from that class).
因为儿子不能管老子,所以结论是
illegal
*/

}
void foo(Base b)
{
b.m_protected; // seems legal. why??
/**
new note:
illegal : 儿子不能管老子
原因同 void foo(Base& c)的分析。
*/
}
};






limd 2003-09-08
  • 打赏
  • 举报
回复
以前我看了也很迷惑的,到现在有点感悟了。
robertnet 2003-09-08
  • 打赏
  • 举报
回复
问:C++编译器为我们做了什么?
答:在类的实现过程中添加了this指针。
Test::Test()
{
a = 10;
}为例。
楼主请看,实际C++编译器为我们添油加醋之后的实际运行代码:
Test::Test(Test* this)
{
this->a = 10;
}
其他类似。
cernet 2003-09-08
  • 打赏
  • 举报
回复
请大家看看下面这段程序,它是能够正常编译连接运行的。但是为什么
assign成员函数没有错呢?谁能告诉我c++中关于这种情况的内幕?谢谢!

#include <stdio.h>

class Test {
private:
int a;
int b;
public:
Test(int a_v, int b_v);
void assign(Test *source);//assign成员函数的参数是一个Test类型指针
void print(void);
};

Test::Test(int a_v, int b_v)
{
a = a_v;
b = b_v;
}

void Test::assign(Test *source)
{
a = source->a;
b = source->b;
}

void Test::print()
{
printf("a = %d, b = %d\n", a, b);
}

int main()
{
Test t1(1, 2), t2(3, 4);

t2.assign(&t1);//t1是Test类型对象,用&取得t1的地址就得到一个Test类型的指针

t2.print();

return 0;
}
assign成员函数的参数是一个Test类型指针
t1是Test类型对象,用&取得t1的地址就得到一个Test类型的指针
这当然没有挑剔的,当然编译通过了
zss6587 2003-09-08
  • 打赏
  • 举报
回复
"cchm(using namespace std)
c++里,类的访问权限是class level,不是object level的。
访问权限只在编译时对编译器有效,在运行时,不存在访问权限这道栅栏。"

言简意赅!!!
alan118 2003-09-07
  • 打赏
  • 举报
回复
C++的封装是针对类的,而不是针对对象的
manchesterunite 2003-09-07
  • 打赏
  • 举报
回复
显然是可以的,这个也是我刚刚看c++书的时候最疑惑的。
比如这样的代码:
#include <iostream>
using namespace std;

class Test{
public:
Test();
Test( const Test & );
void print() const;
private:
int a;
};

Test::Test()
{
a = 10;
}

Test::Test( const Test &oT )
{
a = oT.a;
}

void Test::print() const
{
cout << a ;
}

int main(){
class Test t1,t2(t1);
t2.print();
return 0;
}

就完全可以编译通过,在里面构造函数的重载中,同一个类的对象之间的“毫无隐私”起到了十分重要的作用。
个人决的这和对象的封装有矛盾之处,他的确只对类进行了封装,而对象之间(同类对象)却是“坦诚相见”的。
SingleEyelid 2003-09-07
  • 打赏
  • 举报
回复
我觉的你在问这个问题之前可以自己先测试一下,这样你就知道该不该问这个问题啦.
williamVII 2003-09-07
  • 打赏
  • 举报
回复
quote: wbh0360(剑仙): C++的封装是针对类的,而不是针对对象.

That is the answer.
A simple truth in C++.
A design desision.
If otherwise,the usage of member funtion would be too limited.
Of course,you can write some special member funtion which
provide you the access to private members.
However,add such funtions to your class is obviously an overhaed
which goes against the objective of C++.


Oversense 2003-09-07
  • 打赏
  • 举报
回复
当然可以了
java也可以,理由就是 封装的层次在类上,而不是对象
还有,如果你写编译器,也希望这么写啊
加载更多回复(21)

64,371

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧