C++ 虚函数及重载、重定义、重写
#include<iostream>usingnamespace std;class BASE{public:BASE()=default;BASE(int publicValue,int protectedVale,int privateValue){this->publicValue = publicValue;this->protectedValue = protectedVale;this->privateValue = privateValue;}virtualint getPubValue(int value =0){cout <<"BASE"<< endl;publicValue = value;return publicValue;}/**< 注意不是virtual函数 */int getProValue(){return protectedValue;}public:int publicValue;protected:int protectedValue;private:int privateValue;};class INHERT :public BASE{public:INHERT(int pubValue,int proValue,int priValue):BASE(pubValue, proValue, priValue){}/**< 访问从父类继承的public成员 */int getPubValue(int value =1) override{cout <<"INHERT"<< endl;publicValue = value;return publicValue;}/**< 访问从父类继承的protected成员 */// int getProValue()// {// return protectedValue;// }/**< 从父类继承来的private成员,在子类中是不可访问的。*/// int getPriValue()// {// return privateValue;// }/**< 将会隐藏基类中的同名函数,与参数类型或者参数的顺序无关 */int getProValue(int value){protectedValue = value;return protectedValue;}/**< 通过添加using BASE::getProValue; 将基类所有getProValue函数的重载版本添加到派生类的作用域中去*//**< 在派生类中可以添加新的重载版本,或者覆盖已有的重载版本 */using BASE::getProValue;};int main(){INHERT inhert(4,5,6);BASE * base =&inhert;/**< 虽然调用的是派生类的getPubValue()函数,但是由于该函数在基类和派生类中都带有默认值,所以该函数使用的是基类中的默认值 */cout << base->getPubValue()<< endl;/**< 由于在派生类中重新定义了getProValue函数,则从父类继承的getProValue()将会被隐藏*///cout << inhert.getProValue() << endl;cout << inhert.getProValue(100)<< endl;/**< 显式调用被隐藏函数 */cout << inhert.BASE::getProValue()<< endl;/**< 通过添加using BASE::getProValue; 将基类所有getProValue函数的重载版本添加到派生类的作用域中去*//**< 在派生类中可以添加新的重载版本,或者覆盖已有的重载版本 */cout << inhert.getProValue()<< endl;return0;}
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++ 虚函数及重载、重定义、重写的更多相关文章
- C++学习笔记 封装 继承 多态 重写 重载 重定义
C++ 三大特性 封装,继承,多态 封装 定义:封装就是将抽象得到的数据和行为相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成类,其中数据和函数都是类的成员,目的在于将对 ...
- c++ 多态,虚函数、重载函数、模版函数
c++三大特性:封装.继承.多态.封装使代码模块化,继承扩展已存在的代码,多态的目的是为了接口重用 虚函数实现:虚函数表:指针放到虚函数表 多态:同名函数对应到不同的实现 构造父类指针指向子类的对象 ...
- 虚函数的使用 以及虚函数与重载的关系, 空虚函数的作用,纯虚函数->抽象类,基类虚析构函数使释放对象更彻底
为了访问公有派生类的特定成员,可以通过讲基类指针显示转换为派生类指针. 也可以将基类的非静态成员函数定义为虚函数(在函数前加上virtual) #include<iostream> usi ...
- C++基础:虚函数、重载、覆盖、隐藏<转>
转自:http://www.2cto.com/kf/201404/291772.html 虚函数总是跟多态联系在一起,引入虚函数可以使用基类指针对继承类对象进行操作! 虚函数:继承接口(函数名,参数, ...
- c++虚函数与重载
class base{ public: virtual void f(int n){ cout << "base"<<endl; } }; class De ...
- Visual Studio编译时报错“函数名:重定义;不同的基类型”
错误原因: 方法在还未声明的地方就使用了.由于使用的地方与定义的地方都是在同一个.c文件中,所以没有报未声明的错误. 解决方法: 把实现放到使用的前面,或者在include语句和宏定义后面加上函数声明 ...
- 重载重写重定义-易混淆概念-C++编译器处理方式
1.函数重载 1)必须在同一个类中进行. 2)子类无法重载父类的函数,父类同名函数将被名称覆盖 3)重载是在编译期间根据参数类型和个数决定函数调用 2.函数重写 1)必须发生于父类与子类之间 2)并且 ...
- <转>C++继承中虚函数的使用
转自:http://blog.csdn.net/itolfn/article/details/7412364 一:继承中的指针问题. 1. 指向基类的指针可以指向派生类对象,当基类指针指向派生类对 ...
- C++ 类的多态二(函数重载--函数重写--函数重定义)
//函数重载--函数重写--函数重定义 #include<iostream> using namespace std; /* 函数重载: 必须在一个类中进行(子类无法重载父类中的函数) 子 ...
随机推荐
- MySQL 第六篇:数据备份、pymysql模块
一 IDE工具介绍 生产环境还是推荐使用mysql命令行,但为了方便我们测试,可以使用IDE工具 下载链接:https://pan.baidu.com/s/1O8hXkdRK5_EVHZwNPwjCB ...
- 团体程序设计天梯赛 L3-012. 水果忍者
/*对于一条满足条件的直线,向下移,直到触碰一条线段的下端点,仍然经过其它线段,该直线仍然满足条件 即以一条线段的下(上)端点作为直线上的一点,求为了经过一条线段的最小.最大斜率值(mink,maxk ...
- Service Fabric Cluster Manager
作者:潘罡 (Van Pan)@ Microsoft 我们回到Service Fabric最底层的话题,谈谈Service Fabric是怎么工作的. 首先,我们回到下面的文档,看看Service F ...
- VS批处理命令使用
在项目开始生成或者生成完成后想做一些操作,比如去编译非解决方案下的的项目,完成编译后复制文件到某个文件夹之类的纠结需求. 1. 基本使用 预先生成事件命令行,可以在项目编译的过程中运行 后期生成事件命 ...
- 5 Kafka 应用问题经验积累
16.Kafka 配置文件同步 为了给kafka的进程添加GC日志信息,方便在以后重启的时候,加入GC日志: 修改bin/kafka-server-start.sh: export KAFKA_OPT ...
- 关于Linux用户名
1.创建/删除/修改用户名 useradd 选项 用户名其中各选项含义如下: 代码:-c comment 指定一段注释性描述.-d 目录 指定用户主目录,如果此目录不存在,则同时使用-m选项,可以创建 ...
- Shell记录-Shell脚本基础(二)
Shell 基本运算符 算术运算符: 运算符 描述 例子 + Addition - Adds values on either side of the operator `expr $a + $b` ...
- [Baltic2009]Radio Transmission
bzoj 1355: [Baltic2009]Radio Transmission http://www.lydsy.com/JudgeOnline/problem.php?id=1355 Time ...
- 网络编程之python zeromq学习系列之一
简介: zeromq中间件,他是一个轻量级的消息中间件,传说是世界上最快的消息中间件,为什么这么说呢? 因为一般的消息中间件都需要启动消息服务器,但是zeromq这厮尽然没有消息服务器,他压根没有消息 ...
- Elasticsearch技术解析与实战(五)Document解析
1.手动指定document id 一般来说,是从某些其他的系统中,导入一些数据到es时,会采取这种方式,就是使用系统中已有数据的唯一标识,作为es中document的id. PUT /index/t ...