1. #include<iostream>
  2. usingnamespace std;
  3. class BASE
  4. {
  5. public:
  6. BASE()=default;
  7. BASE(int publicValue,int protectedVale,int privateValue)
  8. {
  9. this->publicValue = publicValue;
  10. this->protectedValue = protectedVale;
  11. this->privateValue = privateValue;
  12. }
  13. virtualint getPubValue(int value =0)
  14. {
  15. cout <<"BASE"<< endl;
  16. publicValue = value;
  17. return publicValue;
  18. }
  19. /**< 注意不是virtual函数 */
  20. int getProValue()
  21. {
  22. return protectedValue;
  23. }
  24. public:
  25. int publicValue;
  26. protected:
  27. int protectedValue;
  28. private:
  29. int privateValue;
  30. };
  31. class INHERT :public BASE
  32. {
  33. public:
  34. INHERT(int pubValue,int proValue,int priValue):
  35. BASE(pubValue, proValue, priValue)
  36. {}
  37. /**< 访问从父类继承的public成员 */
  38. int getPubValue(int value =1) override
  39. {
  40. cout <<"INHERT"<< endl;
  41. publicValue = value;
  42. return publicValue;
  43. }
  44. /**< 访问从父类继承的protected成员 */
  45. // int getProValue()
  46. // {
  47. // return protectedValue;
  48. // }
  49. /**< 从父类继承来的private成员,在子类中是不可访问的。*/
  50. // int getPriValue()
  51. // {
  52. // return privateValue;
  53. // }
  54. /**< 将会隐藏基类中的同名函数,与参数类型或者参数的顺序无关 */
  55. int getProValue(int value)
  56. {
  57. protectedValue = value;
  58. return protectedValue;
  59. }
  60. /**< 通过添加using BASE::getProValue; 将基类所有getProValue函数的重载版本添加到派生类的作用域中去*/
  61. /**< 在派生类中可以添加新的重载版本,或者覆盖已有的重载版本 */
  62. using BASE::getProValue;
  63. };
  64. int main()
  65. {
  66. INHERT inhert(4,5,6);
  67. BASE * base =&inhert;
  68. /**< 虽然调用的是派生类的getPubValue()函数,但是由于该函数在基类和派生类中都带有默认值,所以该函数使用的是基类中的默认值 */
  69. cout << base->getPubValue()<< endl;
  70. /**< 由于在派生类中重新定义了getProValue函数,则从父类继承的getProValue()将会被隐藏*/
  71. //cout << inhert.getProValue() << endl;
  72. cout << inhert.getProValue(100)<< endl;
  73. /**< 显式调用被隐藏函数 */
  74. cout << inhert.BASE::getProValue()<< endl;
  75. /**< 通过添加using BASE::getProValue; 将基类所有getProValue函数的重载版本添加到派生类的作用域中去*/
  76. /**< 在派生类中可以添加新的重载版本,或者覆盖已有的重载版本 */
  77. cout << inhert.getProValue()<< endl;
  78. return0;
  79. }

1 在C++中,有以下几个概念
重定义(redefine):派生类基类的成员函数重新定义(即派生类定义了某个函数)该函数的名字与基类中的函数名字一样。
重载(overload):函数名字相同,但它的形参个数或者顺序(或者类型不同)注意不能靠返回类型来判断。
重写(override):派生类重定义基类虚函数(即会覆盖基类的虚函数)。

如果在派生类中定义了一个与基类同名的函数,不管这个函数的参数列表是不是与基类中的函数相同,则这个同名的函数就会把基类中的所有这个同名的函数的所有重载版本都隐藏了,这时并不是在派生类中重载基类的同名成员函数,而是隐藏。

比如你的基类中有一个成员函数:void func(int i);而子类中又定义了一个void func();那么此时,基类中的void func(int i)就被自动隐藏了,子类对象不能直接调用它。

覆盖:(特征标全部相同的虚函数-原型相同)
如果派生类覆盖了基类中的成员函数或成员变量,则当派生类的对象调用该函数或变量时是调用的派生类中的版本,当用基类对象调用该函数或变量时是调用的基类中的版本。

2 怎样使用派生类的对象访问基类中被派生类覆盖或隐藏了的函数或变量

方法 1 使用作用域运算符:

在使用对象调用基类中的函数或变量时使用作用域运算符即语句 m.A::f(2),这时就能访问基类中的函数或变量版本。

注意,访问基类中被派生类覆盖了的成员变量只能用这种方法

方法 2 使用 using:

该方法只适用于被隐藏或覆盖的基类函数,在派生类的类声明中使用语句 using 把基类的名字包含进来(注意子类的重定义),比如using A::f;就是将基类中的函数f()的所有重载版本包含进来,重载版本被包含到子类之后,这些重载的函数版本就相当于是子类的一部分,这时就可以用派生类的对象直接调用被派生类隐藏了的基类版本,比如 m.f(2),但是使用这种语句还是没法调用基类在派生类中被覆盖了的基类的函数,比如 m.f()调用的是派生类中定义的函数f,要调用被覆盖的基类中的版本要使用语句m.A::f()才行。

在派生类的函数中调用基类中的成员变量和函数的方法:就是在函数中使用的被派生类覆盖的基类成员变量或函数
前用作域解析符加上基类的类名,即a::f()就是在派生类的函数中调用基类中被派生类覆盖了的函数f()的方法。

派生类以私有方式被继承时改变基类中的公有成员为公有的方法:
使用::作用域运算符,不提倡用这种方法,在派生类的 public 后面用作用域运算符把基类的 公有成员包含进来,这样基类的成员就会成为派生类中的公有成员了,注意如果是函数的 话后面不能加括号 ,如A::f;如果f是函数的话不能有括号。
使用using语句,现在一般用这种方法,也是在派生类的public使用using把基类成员包函进来,如using  A::f。

3 如何设计类函数

  • 对于希望子类重写的函数,也就是说基类可以提供自己的一份实现或者不提供实现,但是子类必须拥有自己的实现。一般采用虚函数或者纯虚函数;

  • ​对于一般的成员函数,在子类中不要进行重新定义,一般继承父类的实现即可;

C++ 虚函数及重载、重定义、重写的更多相关文章

  1. C++学习笔记 封装 继承 多态 重写 重载 重定义

    C++ 三大特性 封装,继承,多态 封装 定义:封装就是将抽象得到的数据和行为相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成类,其中数据和函数都是类的成员,目的在于将对 ...

  2. c++ 多态,虚函数、重载函数、模版函数

    c++三大特性:封装.继承.多态.封装使代码模块化,继承扩展已存在的代码,多态的目的是为了接口重用 虚函数实现:虚函数表:指针放到虚函数表 多态:同名函数对应到不同的实现 构造父类指针指向子类的对象 ...

  3. 虚函数的使用 以及虚函数与重载的关系, 空虚函数的作用,纯虚函数->抽象类,基类虚析构函数使释放对象更彻底

    为了访问公有派生类的特定成员,可以通过讲基类指针显示转换为派生类指针. 也可以将基类的非静态成员函数定义为虚函数(在函数前加上virtual) #include<iostream> usi ...

  4. C++基础:虚函数、重载、覆盖、隐藏<转>

    转自:http://www.2cto.com/kf/201404/291772.html 虚函数总是跟多态联系在一起,引入虚函数可以使用基类指针对继承类对象进行操作! 虚函数:继承接口(函数名,参数, ...

  5. c++虚函数与重载

    class base{ public: virtual void f(int n){ cout << "base"<<endl; } }; class De ...

  6. Visual Studio编译时报错“函数名:重定义;不同的基类型”

    错误原因: 方法在还未声明的地方就使用了.由于使用的地方与定义的地方都是在同一个.c文件中,所以没有报未声明的错误. 解决方法: 把实现放到使用的前面,或者在include语句和宏定义后面加上函数声明 ...

  7. 重载重写重定义-易混淆概念-C++编译器处理方式

    1.函数重载 1)必须在同一个类中进行. 2)子类无法重载父类的函数,父类同名函数将被名称覆盖 3)重载是在编译期间根据参数类型和个数决定函数调用 2.函数重写 1)必须发生于父类与子类之间 2)并且 ...

  8. <转>C++继承中虚函数的使用

      转自:http://blog.csdn.net/itolfn/article/details/7412364 一:继承中的指针问题. 1. 指向基类的指针可以指向派生类对象,当基类指针指向派生类对 ...

  9. C++ 类的多态二(函数重载--函数重写--函数重定义)

    //函数重载--函数重写--函数重定义 #include<iostream> using namespace std; /* 函数重载: 必须在一个类中进行(子类无法重载父类中的函数) 子 ...

随机推荐

  1. bzoj3672【NOI2014】购票

    题目描述   今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会.        全国的城市构成了一棵以SZ市为根的有根树,每个城市与 ...

  2. 使用 swoole 加速你的 laravel

    在此前的另外一篇文章讨论过 opcache:php 性能优化之opcache - 让你的php性能提升 50% 再来复习一下吧,导致 php 慢的各种因素中解析性语言的特性可以说是罪魁祸首,再加上,每 ...

  3. golang json 编码解码

    json 编码 package main import ( "encoding/json" "fmt" ) type Person struct { Name ...

  4. 四、java面向对象编程_2

    目录 六.对象的创建和使用 七.this关键字 八.static关键字 九.package和import语句 十.类的继承 十一.访问控制 十二.方法的重写 十三.super关键字 十四.继承中的构造 ...

  5. Linux /etc/issue 和 /etc/issue.net的作用和区别

    1./etc/motd /etc/motd即messageoftoday(布告栏信息),每次用户登录时,/etc/motd文件的内容会显示在用户的终端.系统管理员可以在文件中编辑系统活动消息,例如:管 ...

  6. Hadoop生态圈-Hive的自定义函数之UDAF(User-Defined Aggregation Function)

    Hadoop生态圈-Hive的自定义函数之UDAF(User-Defined Aggregation Function) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  7. Shell记录-Shell脚本基础(二)

    Shell 基本运算符 算术运算符: 运算符 描述 例子 + Addition - Adds values on either side of the operator `expr $a + $b` ...

  8. nginx 跨域配置

    server { listen 80; server_name b.com; location /{ if ( $http_referer ~* (a.com|b.com|c.com) ) { Acc ...

  9. 20155212 2016-2017-2《Java程序设计》课程总结

    每周博客 每周作业链接汇总 预备作业一:专业理解.未来展望.期望的师生关系. 预备作业二:HOMEWORK-2 预备作业三:HOMEWORK-3 第一周作业:学习教材Chapter 1 Java平台概 ...

  10. 微服务深入浅出(8)-- 配置中心Spring Cloud Config

    Config Server从本地读取配置文件 将所有的配置文件统一写带Config Server过程的目录下,Config Server暴露Http API接口,Config Client调用Conf ...