1,父子间的赋值兼容:

1,子类对象可以当做父类对象使用(赋值兼容性):

1,子类对象可以直接赋值给父类对象;

2,子类对象可以直接初始化父类对象;

3,父类指针可以直接指向子类对象(得到的是子类对象);

4,父类引用可以直接引用子类对象;

2,子类对象的兼容性编程实验:

  1. #include <iostream>
  2. #include <string>
  3.  
  4. using namespace std;
  5.  
  6. class Parent
  7. {
  8. public:
  9. int mi;
  10.  
  11. void add(int i)
  12. {
  13. mi += i;
  14. }
  15.  
  16. void add(int a, int b)
  17. {
  18. mi += (a + b);
  19. }
  20. };
  21.  
  22. class Child : public Parent
  23. {
  24. public:
  25. int mv;
  26.  
  27. void add(int x, int y, int z)
  28. {
  29. mv += (x + y + z);
  30. }
  31. };
  32.  
  33. int main()
  34. {
  35. Parent p;
  36. Child c;
  37.  
  38. p = c; // 赋值兼容性的第一种体现;
  39.  
  40. Parent p1(c); // 赋值兼容性的第一种体现;
  41.  
  42. Parent& rp = c; // 赋值兼容性的第二种体现;
  43. Parent* pp = &c; // 赋值兼容性的第二种体现;
  44.  
  45. rp.mi = ;
  46. rp.add(); // 这里 rp 指向子类,应该是不可以访问被同名覆盖的 add(int),但是没有报错;也就是可以访问 add(int),这里没有发生同名覆盖,子类对象已经变成父类对象,只能访问父类当中的成员;
  47. rp.add(, ); // 这里 rp 指向子类,应该是不可以访问被同名覆盖的 add(int, int),但是没有报错;也就是可以访问add(int, int),这里没有发生同名覆盖,子类对象已经变成父类队像,只能访问父类中的成员;
  48.  
  49. /* 为什么编译不过?子类对象已经变成父类对象,没办法访问子类对象中的成员 */
  50. // pp->mv = 1000; // 'class Parent' has no member named 'mv'
  51. // pp->add(1, 10, 100); // no matching function for call to 'Parent::add(int, int, int)'
  52. // candidates are: int Parent::add(int)
  53. // int Parent::add(int, int)
  54.  
  55. return ;
  56. }

3,当使用父类指针(引用)指向子类对象时:

1,子类对象完全退化为父类对象;

2,只能访问父类中定义的成员;

1,通过这个指针或者引用只能访问父类当中的成员,绝对不可以访问子类当中的成员;

3,可以直接访问被子类覆盖的同名成员;

4,特殊的同名函数:

1,子类中可以重定义父类中已经存在的成员函数;

2,这种重定义发生在继承中,叫做函数重写;

3,函数重写是同名覆盖的一种特殊情况;

1,子类当中定义的函数原型和父类当中定义的函数原型一模一样,这叫函数重写;

2,意味着在子类当中重新实现了父类当中的函数;

3,有必要重写实现吗?

1,有必要,如果定义了子类对象,调用了 print() 后,显然的期望打印的是 "I'm Child",证明自己是子类对象,如果打印的是 "I'm   Paretn."就会很奇怪,明明是子类对象,但是却打印父类信息;

2,所以这个函数到了子类当中必须重写,必须重定义,不能再用父类中的函数版本了;

4,以后这种情况统一叫做“函数重写”;

5,思考:

1,当函数重写遇上赋值兼容会发生什么?

1,只能是退化为父类指针或引用;

6,赋值兼容的问题编程实验:

  1. #include <iostream>
  2. #include <string>
  3.  
  4. using namespace std;
  5.  
  6. class Parent
  7. {
  8. public:
  9. int mi;
  10.  
  11. void add(int i)
  12. {
  13. mi += i;
  14. }
  15.  
  16. void add(int a, int b)
  17. {
  18. mi += (a + b);
  19. }
  20.  
  21. void print()
  22. {
  23. cout << "I'm Parent." << endl;
  24. }
  25. };
  26.  
  27. class Child : public Parent
  28. {
  29. public:
  30. int mv;
  31.  
  32. void add(int x, int y, int z)
  33. {
  34. mv += (x + y + z);
  35. }
  36.  
  37. void print()
  38. {
  39. cout << "I'm Child." << endl;
  40. }
  41. };
  42.  
  43. void how_to_print(Parent* p)
  44. {
  45. p->print(); // 当程序编译到这里了,需要通过 p 指针调用 print() 函数,编译器不知道参数 p 指针指向的是父类对象还是子类对象,因为程序还没运行,实参数还没传进来;于是编译器这样假设认为:根据赋值兼容性原则,p 指针所指向的都是父类对象;
  46. }
  47.  
  48. int main()
  49. {
  50. Parent p;
  51. Child c;
  52.  
  53. p.print(); // 打印 I'm Parent.
  54. c.print(); // 当子类中不重写 print() 函数时,打印 I'm Parent.;当子类中重写 print() 函数时,打印 I'm Child.;因此重写很有必要;
  55.  
  56. how_to_print(&p); // Expected to print: I'm Parent. 打印 I'm Parent;
  57. how_to_print(&c); // Expected to print: I'm Child. 打印 I'm Parent;
  58.  
  59. return ;
  60. }

7,父子间的赋值兼容:

1,问题分析:

1,编译期间,编译器只能根据指针的类型判断所指向的对象;

2,根据赋值兼容,编译器认为父类指针指向的是父类对象;

3,因此,编译结果只可能是调用父类中定义的同名函数;

2,实例分析:

void how_to_print(Parent* p)

{

P->print();

}

1,在编译这个函数的时候,编译器不可能知道指针 p 究竟指向了什么,但是编译器没有理由报错(因为单看这个函数语法实现没有错误);于是,编译器认为最安全的做法是调用父类的 print 函数,如果运行时实参是子类对象,根据赋值兼容性原则,将 p->print() 函数解释为父类函数也是合理的,父类和子类肯定都有相同的 print 函数;

3,编译器的处理方法是合理的吗?是期望的吗?

1,同名覆盖带来的问题,当子类重写了父类的某一个函数时,就有可能带来这样的问题;

2,这种处理方法是合理的;

3,这种结果不是我们期望的,之所以重写父类中的函数,是因为父类中的 函数版本不能满足我们的需求了,所以我们重写了父类中的版本,但是 运行的时候还是调用父类中实现的函数,显然不是我们期望的结果;

8,小结:

1,子类对象可以当作父类对象使用(赋值兼容);

1,赋值或初始化,指针或引用;

2,父类指针可以正确的指向子类对象;

3,父类引用可以正确的代表子类对象;

4,子类中可以重写父类中的成员函数;

C++中的赋值兼容性和重写的更多相关文章

  1. 【Java EE 学习 70 下】【数据采集系统第二天】【Action中User注入】【设计调查页面】【Action中模型赋值问题】【编辑调查】

    一.Action中User注入问题 Action中可能会经常用到已经登陆的User对象,如果每次都从Session中拿会显得非常繁琐.可以想一种方法,当Action想要获取User对象的时候直接使用, ...

  2. js中setAttribute 的兼容性

    js中setAttribute 的兼容性class和className兼容方法: object.setAttribute("class","content") ...

  3. C++ 抽象类一(多继承与赋值兼容性原则)

    //多继承与赋值兼容性原则 #include<iostream> using namespace std; class Point{ public: Point(){ a = ; b = ...

  4. 【转】Python中的赋值、浅拷贝、深拷贝介绍

    这篇文章主要介绍了Python中的赋值.浅拷贝.深拷贝介绍,Python中也分为简单赋值.浅拷贝.深拷贝这几种"拷贝"方式,需要的朋友可以参考下   和很多语言一样,Python中 ...

  5. python中的赋值操作和复制操作

    之前一直写C#,变量之间赋值相当于拷贝,修改拷贝变量不会改变原来的值.但是在python中发现赋值操作本质是和C++中的引用类似,即指向同一块内存空间.下面通过一个例子说明: p=[0,1,2,3,4 ...

  6. python中的赋值操作

    参考:https://www.cnblogs.com/andywenzhi/p/7453374.html?tdsourcetag=s_pcqq_aiomsg(写的蛮好) python中的赋值操作“=” ...

  7. php中对象赋值问题

    今天遇到一个问题, 一开始拼接的SQL语句,然后想多次使用时发现会被重置,然后想到给重新赋值一次,但是发现这样赋值会出问题,百思不得其解,最后经过搜索,发现PHP中对象赋值给一个变量之类的赋值的其实是 ...

  8. (网页)Angular.js 中 copy 赋值与 = 赋值 区别

    转自st.gg Angular.js 中 copy 赋值与 = 赋值 区别 为什么用 $scope.user = $scope.master; $scope.master 会跟着 $scope.use ...

  9. ajax实现给JavaScript中全局变量赋值(转)

    原文地址:ajax实现给JavaScript中全局变量赋值 问题简化: <script type="text/javascript"> var a=1 ; functi ...

随机推荐

  1. pycharm修改字体大小和主题

    一,修改文字大小: 二,修改主题:你可能对编辑器的外观仍不满意,例如你希望将文档字符串改变为另外一种颜色,下面介绍具体更改方法:  

  2. LeetCode Array Easy 448. Find All Numbers Disappeared in an Array

    Description Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear ...

  3. tensorflow用dropout解决over fitting

    在机器学习中可能会存在过拟合的问题,表现为在训练集上表现很好,但在测试集中表现不如训练集中的那么好. 图中黑色曲线是正常模型,绿色曲线就是overfitting模型.尽管绿色曲线很精确的区分了所有的训 ...

  4. python 异常处理【转载】

    什么是异常?异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行.一般情况下,在Python无法正常处理程序时就会发生一个异常.异常是Python对象,表示一个错误.当Python脚本 ...

  5. 一、dynamic

    一.dynamic使用: 从一直使用动态类型写接口 返回动态类型出现情况 1.返回接口每次不知道包含那些列(实体类解决) 2.操作的数据类型 不可知(参与数值计算-实体类解决明确类型) Dynamic ...

  6. go语言从例子开始之Example32.打点器

    定时器 是当你想要在未来某一刻执行一次时使用的 - 打点器 则是当你想要在固定的时间间隔重复执行准备的.这里是一个打点器的例子,它将定时的执行,直到我们将它停止. Example: package m ...

  7. 关于WTSAPI32

    一般在windows编程都是用用从ntdll导出的Native API,现在看到一点COM编程或者其他的一些不常用的接口函数总觉得蛮有意思,准备以后多积累一下. 先简单总结WTSAPI32.以下实在W ...

  8. CS184.1X 计算机图形学导论(第三讲)

    第一单元(介绍关于变换的数学知识) :基本二维变换 模型坐标系,世界坐标系 1.缩放 Scale(规模,比例) Sx表示在x方向上放大的倍数,Sy表示在y方向上放大的倍数,因此X坐标乘以Sx,Y坐标乘 ...

  9. 【读书笔记】Cracking the Code Interview(第五版中文版)

    导语 所有的编程练习都在牛客网OJ提交,链接: https://www.nowcoder.com/ta/cracking-the-coding-interview 第八章 面试考题 8.1 数组与字符 ...

  10. 消息队列之AciveMQ

    activemq安全设置 设置admin的用户名和密码