随笔-145  评论-173  文章-70  trackbacks-0

继承是一个永恒的话题,可是带来的问题却也是多多啊。最近一直在思考一些细节的东西,于是也有了不少收获。今天,当我想要用派生类访问基类的私有成员时,发现问题了……
代码1:(没有问题,对照下面的代码来看错误之处)

 1#include <iostream>
 2using namespace std;
 3class B;
 4class A{
 5int b;
 6public:
 7  friend class B;
 8  int a;
 9  A(int x):a(x) { b = a+1;}
10}
;
11class B:public A{
12public:
13  void print();
14    B(int x):A(x){} //基类定义了一个有参的构造函数时,派生类必须定义构造函数 
15}
;
16void B::print()
17
18  cout << B::a << endl;
19  cout << B::b << endl;
20}

21
22int main()
23{
24B b(4);
25b.print();
26}

27
这里可以看到,结果是正确的,而且还能够访问到基类的私有成员b,证明了自己的想法。其中,将派生类都作为了基类的友元,这个范围未免有点大了,好吧,我缩小点,(问题来了……)
问题代码:
 1#include <iostream>
 2using namespace std;
 3class B;
 4class A{
 5int b;
 6public:
 7  int a;
 8  A(int x):a(x) { b = a+1;}
 9  friend void B::print(); 
10}
;
11class B:public A{
12public:
13  void print();
14  B(int x):A(x){} //基类定义了一个有参的构造函数时,派生类必须定义构造函数 
15}
;
16
17
18void B::print()
19
20  cout << B::a << endl;
21  cout << B::b << endl;
22}

23
24int main()
25{
26B b(4);
27b.print();
28}
变化后的代码仅仅就是将类B的print函数作为基类A的友元,这样,按照道理来说,应该也是可以访问基类的私有成员的。而且从上面那个正确的代码来看,声明为友元之后,确实是可以突破访问权限的,然后,此代码有错误,显示的就是私有成员的不可访问。
一时间感觉世界有点不真实了…………

-------------------------------目前原因正在思考中,如果哪个过客知道答案,后者有自己的见解,不妨占用下你宝贵的时间,留个言吧。

(注记:个人认为,印象中《C++ Primer》中讲到在声明类的成员函数为另外一个类的友元时,需要先定义这个类,而如果是派生类的话,可以声明下,等后来再定义。这个也是代码1的做法,没有问题。所以我觉得可能是如果用下面的代码,那么没有先定义类B,而声明了它的成员函数print,所以有问题。待求证……)




结束:
感谢Sunshine Alike  ,我觉得他的解释可能是比较合理的,摘抄如下,如果有误,欢迎留言指正。。
代码2中,仅仅声明类B是无法得知类内部具体实现的,所以你这个时候指定
B中的一个函数作为友元是不行的,因为在这个时候编译器还不知道B的具体实现是怎么样的。
代码1:开始时声明类B,将其整个类作为友元类,编译器无需知道其内部实现,所以可以通过

posted on 2010-01-12 23:53 deercoder 阅读(4128) 评论(10)  编辑 收藏 引用

评论:
# re: C++友元的一个问题-----------由派生类访问基类的私有成员 2010-01-13 01:15 | zhaoyg
刚才在看到friend void B::print(); 这句时就已经觉得问题就是由他引发的。
因为我记得如果是要将类的成员作为友元,那该类就应该是已定义的。

经编译,得到验证
报错如下:
error: member `void B::print()' declared as friend before type `B' defined
C++ Primer 上也说得是“必须先定义一个类,才能将成员函数设为友元”

还有,
“而如果是派生类的话,可以声明下,等后来再定义”
这句话我没有在C++ Primer 上找到。  回复  更多评论
  
# re: C++友元的一个问题-----------由派生类访问基类的私有成员 2010-01-13 10:39 | 刘畅
@zhaoyg
谢谢你的回答。
对于这个错误,我开始的看法和你是一样的,认为必须先要定义一个类,然后再可以声明它的函数是另一个类的友元。
可是,看看前面的代码1我就觉得有点不对,因为对于class B,先开始的时候只是声明,而没有定义,这样却可以将整个类作为它的友元,我觉得也有点不可行。不然,这样不是和上面的一个道理吗?  回复  更多评论
  
# re: C++友元的一个问题-----------由派生类访问基类的私有成员 2010-01-13 11:18 | Sunshine Alike
@刘畅
代码2中,仅仅声明类B是无法得知类内部具体实现的,所以你这个时候指定
B中的一个函数作为友元是不行的,因为在这个时候编译器还不知道B的具体实现是怎么样的。
代码1:开始时声明类B,将其整个类作为友元类,编译器无需知道其内部实现,所以可以通过  回复  更多评论
  
# re: C++友元的一个问题-----------由派生类访问基类的私有成员 2010-01-13 12:31 | 刘畅
@Sunshine Alike
有道理,其实前面也觉得可能跟类的实现有关吧,学习了~~~  回复  更多评论
  
# re: C++友元的一个问题-----------由派生类访问基类的私有成员 2010-09-21 07:39 | @kll
友元的访问权限 与类的继承你搞混了  回复  更多评论
  
# re: C++友元的一个问题-----------由派生类访问基类的私有成员 2010-09-21 07:51 | @kll
原来不注册可以留言 呵呵 上面说的只是测试 下面说下我理解不知道对不对
code1 中将类B设为A的友元 B又是A的public继承 那么B能访问A的private成员是因为友元的缘故 B::b等价于 B:: A::b 故B.print() 可以执行
code2 只是将B的成员print()设为A的友元 那么B::b 则不成立 无法访问吧
若是 print 函数带A对象的引用会通过的

我了解的这一点不多 其实我是想查询关于公有派生类的友元 能不能访问基类的private的成员 或者访问权限到那一层 在继承层次中友元的权限又有哪些 这方面的文章 如果斑竹有资料 望不吝赐教 谢谢 忘了打标点 估计看起来麻烦 呵呵 我没有代码运行的环境 要不然能测试了 呵呵  回复  更多评论
  
# re: C++友元的一个问题-----------由派生类访问基类的私有成员 2014-01-12 12:51 | panpan
为什么我将第一种的 A(int x):a(x) { b = a+1;}改为A(int x):a(x),b(a+1) {}运行结果为
4
-858993459
请按任意键继续. . .

为什么 搞不清楚  回复  更多评论
  
# re: C++友元的一个问题-----------由派生类访问基类的私有成员 2014-01-12 12:53 | panpan
哦哦 搞懂了 成员变量是按照在类中声明的先后顺序来初始化的   回复  更多评论
  
# re: C++友元的一个问题-----------由派生类访问基类的私有成员 2014-01-12 13:32 | panpan
我觉得这个派生类成员函数作为基类的成员友元本身就有问题,首先,类B是类A的派生类,那么类A必须在类A前定义,而派生类B的函数print()是基类友元,使得派生类B必须先于A定义(不是声明),这两个前提条件已经互相矛盾,所以怎么都是有问题的  回复  更多评论
  
# re: C++友元的一个问题-----------由派生类访问基类的私有成员 2014-01-12 13:56 | panpan
我试了 第二种情况 即便是传给print()一个A&参数,照样是不能访问b成员变量的 这个确实没想通  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理