C++学习笔记46——友元与继承
来源:互联网 发布:鼎域名邸房价走势 编辑:程序博客网 时间:2024/05/18 03:26
1,总的原则
继承层次中关于友元的总原则就是:友元关系不能继承。可以概述如下:
- 老爸的朋友不一定是我的朋友;
- 朋友的儿子不一定还是朋友;
- 由以上两条不难推出:老爸的朋友的儿子不一定还是朋友
2,验证派生类不能继承基类的友元
// 类的定义struct Frnd;//类的前置声明class Baba{public:friend Frnd;//友元声明,还记得吗?protected:void test() { cout << "I am your father!\n" << endl; }};class Son2: public Baba{private:void son_test() { cout << "I am your son!\n" << endl; }};struct Frnd{//友元可以使用派生类从基类继承的成员,但不能使用派生类自己新定义的成员void check(Baba &f) { f.test(); }void check2(Son2 &s) { s.test(); }//void check3(Son2 &s) { s.son_test(); }//error C2248: “Son2::son_test”: 无法访问 private 成员(在“Son2”类中声明)};//主函数int main(){Baba f;Son2 s;Frnd frd;//1,验证派生类不能继承父类的友元frd.check(f);// OKfrd.check(s);// 居然也OK,使用基类的地方可以使用派生类frd.check2(s);// 居然还OK!}输出如下:
应当注意几点:
- 类Frnd的定义体内不能使用s.son_test()证明了基类的友元不再是派生类的友元;
- check2的定义体证明,派生类中从基类继承过来的成员还是对友元开放的;
- main函数中frd.check(s)的用法,是在需要基类的地方使用public派生类。
3,验证友元、继承与动态绑定
// 结构体定义struct Frnd;class Baba{public:friend Frnd;protected:virtual void test() { cout << "I am your father!\n" << endl; }};class Son2 : public Baba{private:virtual void test() { Baba::test(); cout << "son again!\n"; }void son_test() { cout << "I am your son!\n" << endl; }};struct Frnd{//友元可以使用派生类从基类继承的成员,但不能使用派生类自己新定义的成员void check(Baba &f) { f.test(); }//void check2(Son2 &s) { s.test(); }//error C2248: “Son2::test”: 无法访问 private 成员(在“Son2”类中声明)};//主函数int main(){Baba f;Son2 s;Frnd frd;frd.check(f);// OKfrd.check(s);// 居然也OK}输出结果:
这段代码最让人困惑的地方在于:Frnd中check2定义失败是由于它需要使用Son2::test(),但是在主函数中frd.check(s)借由动态绑定事实上也使用了Son2::test()——这一点可以由输出打印结果确认——但是却运行正确。就好像是用动态绑定骗过了编译器一样。
我们将友元与virtual函数的关系总结如下:
- 我们知道派生类中的成员分为3类:直接继承自基类的成员、重定义的虚函数和自己新增的成员;
- 基类的友元函数可以使用直接继承自基类的成员,不可以使用派生类新增的成员
- 对于派生类重定义的虚函数,基类的友元不能通过派生类的对象直接使用,因为这样必然导致使用的是派生类中的版本;但是可以通过动态绑定使用:即友元名义上用的是指向基类的指针或引用,但实际上该指针或引用指向了派生类的对象,友元中可以使用这种方法使用派生类的virtual成员,别且最终用到的还是派生类中的版本。
//其他地方不变,将check改为值传递版本struct Frnd{//友元可以使用派生类从基类继承的成员,但不能使用派生类自己新定义的成员void check(Baba f) { f.test(); }//void check2(Son2 &s) { s.test(); }//error C2248: “Son2::test”: 无法访问 private 成员(在“Son2”类中声明)};则输出结果如下:
两次使用的都是基类中的版本。
4,验证友元的派生类不再是友元
其他代码不变,增加如下定义:
//3,验证友元的派生类不再是友元struct FrndSon:public Frnd{//error C2248: “Baba::test”: 无法访问 protected 成员(在“Baba”类中声明)//void son_check(Baba &f) { f.test(); }};主函数如下实现:
int main(){Baba f;Son2 s;FrndSon fs;fs.check(f);fs.check(s);}输出结果与上一节一模一样:
总结如下:
- FrndSon中不能使用Baba中的protected成员,证明Frnd对Baba的友元关系没有继承给Frnd的派生类FrndSon;
- FrndSon的对象还是可以使用继承自Frnd的public成员函数check,而check()是Baba的友元,这种友元关系不变。
struct Frnd{//友元可以使用派生类从基类继承的成员,但不能使用派生类自己新定义的成员void check(Baba &f) { f.test(); }virtual void v_check(Baba &f) { f.test(); }//void check2(Son2 &s) { s.test(); }//error C2248: “Son2::test”: 无法访问 private 成员(在“Son2”类中声明)};//3,验证友元的派生类不再是友元struct FrndSon:public Frnd{//error C2248: “Baba::test”: 无法访问 protected 成员(在“Baba”类中声明)//virtual void v_check(Baba &f) { f.test(); }//error C2248: “Baba::test”: 无法访问 protected 成员(在“Baba”类中声明)//void son_check(Baba &f) { f.test(); }};
毫不意外,虚函数同样没有获得友元属性。
其实简单来说就是:友元的派生类(FrndSon)的类定义体中不能用到其他类(Baba)的protected或private成员。
0 0
- C++学习笔记46——友元与继承
- 【C++】学习笔记五十二——友元
- 友元关系与继承——《C++ primer》笔记,书中的小bug
- 友元与继承
- Objective-C学习笔记(二十五)——属性与方法的继承学习
- C++学习笔记:C的继承与超越——指针与引用
- 继承与阻止继承——20170313 学习笔记
- 【C++】【学习笔记】【020】友元
- C++笔记: 继承,友元
- C++学习笔记:C的继承与超越——const关键字
- C++ Primer 学习笔记 — 友元
- 友元关系与继承
- C++ 友元与继承
- 黑马程序员 — Objective-C学习笔记(二):继承
- [C++]友元学习
- C++学习笔记——继承与派生(二)
- C++学习笔记——继承与派生
- C++学习笔记——继承与派生
- 2014年第五届蓝桥杯C/C++程序设计本科B组省赛 蚂蚁感冒(编程大题)
- Java堆、栈和常量池以及相关String的详细讲解(经典中的经典)
- Cocos2d-x 屏幕适配
- 对文件进行操作
- 天才第一步,点亮人生中的第一个发光二极管
- C++学习笔记46——友元与继承
- POJ 3267 The Cow Lexicon DP 字符串匹配 一主串n个子串最少在主串删除多少字母,可以匹配到n 个单词序列中的一些完整单词
- 为什么要用DLL文件
- Leetcode Wiggle Sort II
- 1005. 继续(3n+1)猜想 (25)
- 1035. DNA matching
- opencart安装
- 92. php 命名空间(2)
- android 微信支付 问题解决