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; /* 函数重载: 必须在一个类中进行(子类无法重载父类中的函数) 子 ...
随机推荐
- bzoj 4358: permu 莫队
第一步先莫队分块. 对于每一块l~r,初始右端点设为r+1,然后每个询问先将右端点往右移,然后处理询问在l~r之间的部分,最后用一个栈再把l~r的复原. 具体来说是维护两个数组now1和now2,一个 ...
- bzoj2564集合的面积
题目描述 对于一个平面上点的集合P={(xi,yi )},定义集合P的面积F(P)为点集P的凸包的面积. 对于两个点集A和B,定义集合的和为: A+B={(xiA+xjB,yiA+yjB ):(xiA ...
- (转)Tomcat version 7.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 and 6 Web mod
背景:在sts中导入web项目,却不能通过sts中的tomcat来加载该服务,并报出如下错误. “Tomcat version 7.0 only supports J2EE 1.2, 1.3, 1.4 ...
- 【费用流】【网络流24题】【P1251】 餐巾计划问题
Description 一个餐厅在相继的 \(N\) 天里,每天需用的餐巾数不尽相同.假设第 \(i\) 天需要 \(r_i\)块餐巾.餐厅可以购买新的餐巾,每块餐巾的费用为 \(p\) 分;或者把旧 ...
- go递归打印指定目录下的所有文件及文件夹
func treedir(fpath string){ // 获取fileinfo if finfo,err := os.Stat(fpath); err == nil { // 判断是不是目录 如果 ...
- git<commit和分支>
commit: 在执行提交命令git commit之前,一定要git add要修改的文件,这样才能将更改的内容更新到本地. 在Git 中提交时,会保存一个提交(commit)对象,它包含一个指向暂存内 ...
- codeforces.com/contest/251/problem/C
C. Number Transformation time limit per test 2 seconds memory limit per test 256 megabytes input sta ...
- Lvs+Keepalived实现MySQL高可用
LVS+Keepalived+MySQL高可用配置 本文所有配置前提是已实现MySQL双主备份(MySQL双主) 安装前的准备: VIP:192.168.0.201 Keepalived: Keepa ...
- 动态规划:树形DP-选课(树形背包)
学校开设了N(N<300)门的选修课程,每个学生可选课程的数量M是给定的.学生选修了这M门课并考核通过就能获得相应的学分.在选修课程中,有些课程可以直接选修,有些课程需要一定的基础知识,必须在选 ...
- 你需要了解 Windows Phone 8.1 的11件事
微软已经发布了其新一代手机操作系统 Windows Phone 8.1,拥有一些新的特性.从本质上来说,微软此次的大修让 Windows Phone 更接近 Android 和 iOS,对于使用体验的 ...