C++之重载重写重定义

一 重载(overload)

概念:

函数有同样的名称,但是参数列表不相同的情形,这样的同名不同参数的函数之间,互相称之为重载函数。

基本条件:
  • 函数名必须相同;
  • 函数参数必须不相同,可以是参数类型或者参数个数不同;
  • 函数返回值可以相同,也可以不相同;

注意:
  • 只能通过不同的参数样式进行重载,例如:不同的参数类型,不同的参数个数,不同的参数顺序;
  • 不能通过访问权限、返回类型、抛出的异常进行重载;
  • 重载的函数应该在相同的作用域下

二 重写(override)

概念:

也称为覆盖,子类重新定义父类中有相同名称和参数的虚函数,主要在继承关系中出现。

基本条件:
  • 重写的函数和被重写的函数必须为virtual函数,分别位于基类和派生类中;
  • 重写的函数和被重写的函数函数名和函数参数必须一致;
  • 重写的函数和被重写的函数返回值相同,或者都返回指针或引用,并且派生类虚函数所返回的指针或引用的类型是基类中被替换的虚函数所返回的,如果基类函数返回类型是void,而子类是int编译出错。
  • 指针或引用的类型的子类型。
注意:
  • 重写的函数所抛出的异常必须和被重写的函数所抛出的异常一致,或者是其子类;
  • 重写的函数的访问修饰符可以不同于被重写的函数,如基类的virtual函数的修饰符为private,派生类改为public或protected也是可以的。
  • 静态方法不能被重写,也就是static和virtual不能同时使用。
  • 重写的函数可以带virtual关键字,也可以不带。
验证程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
class A {
};

class B : public A {
};

class C {
 public:
  virtual void Func1() {
    std::cout << "class C: func 1" << std::endl;
  }

  virtual A* Func2() {
    std::cout << "class C: func 2" << std::endl;
    return new A;
  }

  // ERROR:静态函数不能被声明为virtual,也就没办法被重写。
  // static virtual void FuncStatic() {}

  //由于Func3被声明为private,所以需要通过public函数来调用
  void ShowFunc3() {
    Func3();
  }

  virtual void Func4() {
    std::cout << "class C: func 4" << std::endl;
  }

 private:
  virtual void Func3() {
    std::cout << "class C: func 3" << std::endl;
  }
};

class D : public C {
 public:
  // OK: 重写C类Func1,可以不带virtual关键字
  void Func1() {
    std::cout << "class D: func 1" << std::endl;
  }

  // OK: 当返回值为指针或者引用时,返回值可以是父类返回值类型的子类
  virtual B* Func2() {
    std::cout << "class D: func 2" << std::endl;
    return new B;
  }

  // ERROR: 除上面的情况,返回值类型要和父类一直
  /*virtual bool Func2() {
  }*/

  // OK: 重写的函数的访问修饰符可以不同于被重写的函数
  virtual void Func3() {
    std::cout << "class D: func 3" << std::endl;
  }

 private:
  // OK: 重写的函数的访问修饰符可以不同于被重写的函数
  virtual void Func4() {
    std::cout << "class D: func 4" << std::endl;
  }
};

int _tmain(int argc, _TCHAR* argv[])
{
  C* c = new D;
  c->Func1();
  c->Func2();
  c->ShowFunc3();
  c->Func4();
  return 0;
}

输出:

1
2
3
4
class D: func 1
class D: func 2
class D: func 3
class D: func 4

int Func1()将子类void Func1()改为 编译
 error: conflicting return type specified for ‘virtual int D::Func1()’
   int Func1() {
       ^
test.cpp:11:16: error:   overriding ‘virtual void C::Func1()’
   virtual void Func1() {
                ^

三 重定义(redefining)

概念:

也叫隐藏,子类重新定义父类中的非虚函数,屏蔽了父类的同名函数

基本条件:
  • 被隐藏的函数之间作用域不相同
注意:
  • 子类和父类的函数名称相同,但参数不同,此时不管父类函数是不是virtual函数,都将被隐藏。
  • 子类和父类的函数名称相同,参数也相同,但是父类函数不是virtual函数,父类的函数将被隐藏。
  • 子类和父类函数名相同,参数相同,但返回值不同,如果基类是virtual函数,编译出错,如果基类非virtual函数,基类被隐藏
验证程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class A {
public:
  void Func1(int a) {
      std::cout << "class A: Func1" << std::endl;
  }

  virtual void Func2(int a) {
      std::cout << "class A: Func2" << std::endl;
  }
};

class B : public A {
public:
  // 将会重定义父类的方法
  void Func1(int a) {
      std::cout << "class B: Func1" << std::endl;
  }

  // 将会重写(override)父类方法
  void Func2(int a) {
    std::cout << "class B: Func2-1" << std::endl;
  }

  // 将会重定义父类的方法
  void Func2(int a, int b) {
    std::cout << "class B: Func2-2" << std::endl;
  }
};

int _tmain(int argc, _TCHAR* argv[])
{
  B* b = new B;
  b->Func1(1);
  b->Func2(1);
  b->Func2(1, 1);
  return 0;
}

输出:

1
2
3
class B: Func1
class B: Func2-1
class B: Func2-2

四 总结

重载、重写、重定义书面上的区别,以及各自的规则没有太大意义,而且这些名词本身都是翻译过来的,不同的地方翻译也不尽相同,如果初学C++,弄清每个概念的实际意义,以及为什么这么设计才是最重要的。转载请注明出处:http://glgjing.github.io/

# 力扣hot100刷题记录表 ### 一,哈希部分 - [ ] 1. 两数之和 (简单) - [ ] 2. 字母异位词分组(中等) - [ ] 3. 最长连续序列(中等) ### 二,双指针部分 - [ ] 4. 移动零(简单) - [ ] 5. 盛水最多的容器 (中等) - [ ] 6. 三数之和 (中等) - [ ] 7. 接雨水(困难) ### 三,滑动窗口 - [ ] 8. 无重复字符的最长子串(中等) - [ ] 9. 找到字符中所有的字母异位词(中等) ### 四,子串 - [ ] 10. 和为k的子数组(中等) - [ ] 11. 滑动窗口最大值(困难- [ ] 12. 最小覆盖子窜(困难) ### 五,普通数组 - [ ] 13. 最大子数组和(中等) - [ ] 14. 合并区间(中等) - [ ] 15. 轮转数组(中等) - [ ] 16. 除自身以外数组的乘积(中等) - [ ] 17. 缺失的第一个正数(困难) ### 六,矩阵 - [ ] 18. 矩阵置零(中等) - [ ] 19. 螺旋矩阵 (中等) - [ ] 20. 旋转图像 (中等) - [ ] 21. 搜索二维矩阵Ⅱ (中等) ### 七,链表 - [ ] 22. 相交链表 (简单) - [ ] 23. 反转链表 (简单) - [ ] 24. 回文链表 (简单) - [ ] 25. 环形链表 (简单) - [ ] 26. 环形链表Ⅱ (中等) - [ ] 27. 合并两个有序链表 (简单) - [ ] 28. 两数相加 (中等) - [ ] 29. 删除链表的倒数第 N 个结点 (中等) - [ ] 30. 两两交换链表中的节点 (中等) - [ ] 31. K个一组翻转链表 (困难) - [ ] 32. 随机链表的复制 (中等) - [ ] 33. 排序链表 (中等) - [ ] 34. 合并 K 个升序链表 (困难) - [ ] 35. LRU 缓存 (中等) ### 八,二叉树 - [ ] 36. 二叉树的中序遍历 (简单) - [ ] 37. 二叉树的最大深度 (简单) - [ ] 38. 翻转二叉树 (简单) - [ ] 39. 对称二叉树 (简单) - [ ] 40. 二叉树的直径 (简单) - [ ] 41. 二叉树的层序遍历 (中等) - [ ] 42. 将有序数组转换为二叉搜索树 (简单) - [ ] 43. 验证二叉搜索树 (中等) - [ ] 44. 二叉搜索树中第 K 小的元素 (中等) - [ ] 45. 二叉树的右视图 (中等) - [ ] 46. 二叉树展开为链表 (中等) - [ ] 47. 从前序与中序遍历序列构造二叉树 (中等) - [ ] 48. 路径总和 III (中等) - [ ] 49. 二叉树的最近公共祖先 (中等) - [ ] 50. 二叉树中的最大路径和 (困难) ### 九,图论 - [ ] 51. 岛屿数量 (中等) - [ ] 52. 腐烂的橘子 (中等) - [ ] 53. 课程表 (中等) - [ ] 54. 实现 Trie(前缀树) (中等) ### 十,回溯 - [ ] 55.全排列(中等) - [ ] 56.子集(中等) - [ ] 57.电话号码的字母组合(中等) - [ ] 58.组合总和(中等) - [ ] 59.括号生成(中等) - [ ] 60.单词搜索(中等) - [ ] 61.分割回文串(中等) - [ ] 62.N 皇后 (困难) ### 十一,二分查找 - [ ] 63. 搜索插入位置 (简单) - [ ] 64. 搜索二维矩阵 (中等) - [ ] 65. 在排序数组中查找元素的第一个和最后一个位置 (中等) - [ ] 66. 搜索旋转排序数组 (中等) - [ ] 67. 寻找旋转排序数组中的最小值 (中等) - [ ] 68. 寻找两个正序数组的中位数 (困难) ### 十二,栈 - [ ] 69. 有效的括号 (简单) - [ ] 70. 最小栈 (中等) - [ ] 71. 字符串解码 (中等) - [ ] 72. 每日温度 (中等) - [ ] 73. 柱状图中最大的矩形 (困难) ### 十三,堆 - [ ] 74. 数组中的第K个最大元素 (中等) - [ ] 75. 前K 个高频元素 (中等) - [ ] 76. 数据流的中位数 (闲难) ### 十四,贪心算法 - [ ] 77. 买卖股票的最佳时机 (简单) - [ ] 78. 跳跃游戏 (中等) - [ ] 79. 跳跃游戏 III (中等) - [ ] 80. 划分字母区间 (中等) ### 十五,动态规划 - [ ] 81. 爬楼梯(简单) - [ ] 82. 杨辉三角 (简单) - [ ] 83. 打家劫舍 (中等) - [ ] 84. 完全平方数 (中等) - [ ] 85. 零钱兑换 (中等) - [ ] 86. 单词拆分 (中等) - [ ] 87. 最长递增子序列 (中等) - [ ] 88. 乘积最大子数组 (中等) ### 十六,多维动态规划 - [ ] 91. 不同路径 (中等) - [ ] 92. 最小路径和 (中等) - [ ] 93. 最长回文子串 (中等) - [ ] 94. 最长公共子序列 (中等) - [ ] 95. 编辑距离 (中等) ### 十七,技巧 - [ ] 96. 只出现一次的数字 (简单) - [ ] 97. 多数元素 (简单) - [ ] 98. 颜色分类 (中等) - [ ] 99. 下一个排列 (中等) - [ ] 100. 寻找重复数 (中等) 如何使用
最新发布
07-20
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值