转自:http://www.2cto.com/kf/201404/291772.html
虚函数总是跟多态联系在一起,引入虚函数可以使用基类指针对继承类对象进行操作!
虚函数:继承接口(函数名,参数,返回值),但是实现不继承(函数体)
非虚函数:继承接口,也继承实现;
1)虚析构函数(当一个类打算作为基类使用时候,其析构函数必须是虚函数)
构造函数可以为虚函数吗? 不可以,在生成对象的时候,必须向编译器明确指定要生成什么类型的对象,因而不存在虚函数的问题;只有当对象已经存在,我用什么接口去操作它的问题;
例子:
class A
{
public:
A();
virtual~A();
};
class B: public A
{
public:
B();
~B();
};
int main()
{
A *pA=new B; //调用B的构造函数
delete pA;
return 0;
}
这里通过指针A去调用B类的析构函数,但是如果 ~A()不是虚析构函数,就不存在多态,就会去调用A中的析构函数,最后结果可能是B对象中的A成分被析构了,其他 还残留;所以当一个类作为基类时候,其析构函数必须是虚函数,这样防止出现析构不完全的情况;
2)当虚函数出现在构造、析构函数中时(即在构造函数中调用虚函数),函数退化为普通函数。为什么? <>中条款
例子:(转自<>中条例9)
class Transaction
{
public:
Transaction();
virtual void LogTransaction() const = 0;
// ...
};
Transaction::Transaction()
{
// ...
LogTransaction();
}
class BuyTransaction : public Transaction
{
public:
virtual void LogTransaction() const;
// ...
};
这里调用BuyTransaction的构造函数,因为BuyTransaction是继承类所以先调用基类的构造函数,此时派生类独有的那部分还未初始化,<>中这么解释:“这个对象内的BuyTransaction成分还未初始化,最安全的办法是当他不存在,对象在derived成分还未初 始化时该对象不会成为一个derived对象”所以Transaction 的构造函数会调用基类的 LogTransaction() const;而且此处是个纯虚函数,会报错
3)虚函数与覆盖,重载,隐藏
重载首先出现在非继承关系当中,当同一个类中,两个函数的参数不同,名字相同,返回值类型无所谓(函数返回值不作为重载的参考,因为函数调用时候不出现返回值);
注意两个函数可以仅仅因为const与非const的差别来实现重载;
虚函数与覆盖均出现在一个继承体系中,覆盖针对的是普通函数,当父类子类中出现同名(相同返回值,相同参数,相同函数名)要求绝对一致;
虚函数在父类子类中,首先在父类中声明该函数为virtual,那么子类可以重新定义该函数的实现,这里主要涉及多态,就是覆盖的情况加上virtual,通过指针或者引用实现多态;
隐藏显得简单粗暴,在继承类中只要出现于父类同名(只要求同样的函数名/变量名,其他返回值,virtual 非virtual不管)的函数,则用对象调用同名函数时候,基类对应的同名函数、变量隐藏,如果要访问其父类的同名成员应该明确使用 基类名::成员来访问;
例子:
class A
{
public:
virtual ~A(){};
void process(int i,char c); //重载,编译期间即可确定该调用哪个函数
char process(double d,int c); //只要函数名相同,返回无所谓,参数不同
void process(int i);
void process(int i)const; // 此处相当于void process(const A *this,int i);
void process(consttint i); //这里仅仅因为const属性不同即可实现重载
virtual int foo(int, char){...};
int foo2(){};
void foo3(int,int ){};
}
class B: public A
{
public:
int foo(int ,char){...}; //虚函数,这里函数接口要严格一致(大部分编译器要求返回值也要一致)
int process(){...}; //隐藏基类函数
int foo2(){}; // 这里不含虚属性,会覆盖
int foo3(){return 0;}; //会隐藏A类的foo3
}
int main()
{
B b;
A *pA=&b;
pA->foo2(); //这里调用A类的foo2();不涉及多态;
pA->foo(3,'c'); //B类foo() 涉及多态
}
总结:
1)覆盖与虚函数是一对兄弟,要求函数的返回值,函数名,参数严格一致,虚函数是覆盖加上virtual的情况;
2) 隐藏是覆盖的推广,覆盖是隐藏的特例,只要求函数名一样,其他不管,在继承体系中,子类的同名函数会将父类的同名函数隐藏;
3)当使用指针时候,指向基类的指针会根据实际对象的类型,选择相应的虚函数执行,如果派生类没有重新定义基类的虚函数,那么依然执行基类的虚函数;
4)当不存在虚函数的情况下,使用基类的指针,不会下降到派生类中去搜索函数;所以virtual属性相当于告诉基类指针:当执行我时,请到相应对象中搜索对应的虚函数;
5)纯虚函数所在的类是抽象类,不能实例化,定义了纯虚函数意味着这个函数只能为父类,其负责定义接口而不负责实现;
6)当使用对象来调用相应的函数时候,主要考虑的是对基类同名函数的隐藏(包括覆盖),而不需要考虑多态;
7)注意构造析构函数中不能调用虚函数,当执行派生类的构造函数时候,先构造的是其基类成分,再执行派生类成分的构造,虚函数此时无意义;
8)c++是个细节非常多,非常复杂的语言;
C++基础:虚函数、重载、覆盖、隐藏<转>的更多相关文章
-
C++重载覆盖隐藏
写一个程序,各写出重载覆盖 1 // // main.cpp // 2013-7-17作业2 // // Created by 丁小未 on 13-7-17. // Copyright (c) 201 ...
-
C++11显式虚函数重载
[C++11显式虚函数重载] 在子类中给重载的虚函数加上override, 可以让编译器检察基类是否有这一虚函数.此功能适用于当基类原有的虚函数发生变化,即相当于编译期检察. 而基类,可以给函数加上f ...
-
C++ 11 学习3:显示虚函数重载(override)
5.显示虚函数重载 在 C++ 里,在子类中容易意外的重载虚函数.举例来说: struct Base { virtual void some_func(); }; struct Derived : B ...
-
c++ 继承 虚函数与多态性 重载 覆盖 隐藏
http://blog.csdn.net/lushujun2011/article/details/6827555 2011.9.27 1) 定义一个对象时,就调用了构造函数.如果一个类中没有定义任何 ...
-
虚函数重载(overwrite) 继承覆盖问题
引言 类接口需要添加默认参数,以适应不同情况调用, 但是clang-tidy 不允许在接口上设置默认参数,ps: 可能担心继承类里接口重新设置新默认参数而导致误用的情况 #include <st ...
-
c/c++:重载 覆盖 隐藏 overload override overwrite
http://www.cnblogs.com/qlee/archive/2011/07/04/2097055.html 成员函数的重载.覆盖与隐藏成员函数的重载.覆盖(override)与隐藏很容易混 ...
-
c++中 重载 覆盖 隐藏的区别 附加 mutable笔记
成员函数被重载的特征有: 1) 相同的范围(在同一个类中): //2) 函数名字相同: 3) 参数不同: 4) virtual关键字可有可无. 覆盖的特征有: 1) 不同的范围(分别位于派生类与基类) ...
-
C++基础--虚函数和纯虚函数
虚函数的一种重要的应用是在子类重写父类方法上,一般都是在父类中声明的时候用关键字virtual修饰. 在C++中,一个父类的对象指针是可以指向子类的实例化对象,这个时候可以用该对象指针来访问父类的成员 ...
-
C++中的重载,隐藏,覆盖,虚函数,多态浅析
直到今日,才发现自己对重载的认识长时间以来都是错误的.幸亏现在得以纠正,真的是恐怖万分,雷人至极.一直以来,我认为重载可以发生在基类和派生类之间,例如: class A { public: void ...
随机推荐
-
angular2自学笔记---官网项目(一)
1.单向数据绑定的'插值表达式' angular中最典型的数据显示方式:把HTML模板(template)的控件绑定到angular组件的属性(component相当于一个构造函数,下面例子中的这个构 ...
-
22. Generate Parentheses(ML)
22. Generate Parentheses . Generate Parentheses Given n pairs of parentheses, write a function to ge ...
-
SAP 打开SAP物料帐期和财务账期
引http://blog.sina.com.cn/s/blog_494f9a6b0102e8zw.html 物料账期:Tcode MMPV和Tcode MMRV 财务账期:Tcode OKP1 和O ...
-
【ACM-ICPC 2018 沈阳赛区网络预赛】不太敢自称官方的出题人题解
A. Gudako and Ritsuka 链接 by Yuki & Asm.Def 期望难度:Hard- 考虑从后往前进行博弈动态规划,在这一过程中维护所有的先手必胜区间.区间不妨采用左开右 ...
-
python 中安装pandas
由于计算arima模型需要用到pandas,费尽千辛万苦找到了一个下载地址:http://www.lfd.uci.edu/~gohlke/pythonlibs/,在这里能下载到很多我们要用的模块.找到 ...
-
selenium3.0 远程模式
准备工作: 1. 安装chrome浏览器 2. 下载selnium-server-standalone-3.0.1.jar 步骤: 1. java -jar selnium-server-standa ...
-
# 第二周课堂实践以及MyOD
第二周课堂实践以及MyOD 之前使用的虚拟机出现问题被我删掉了,开始学着使用Mac系统自带的终端.在课堂上出现了问题,询问王雄老师也没有解决,课下先使用了实验楼环境进行实验,后来又在Mac重新进行了尝 ...
-
springAOP实现方法运行时间统计
aop的before和after,寻思分别在两个方法里获得当前时间,最后一减就可以了. 因此,今天就探讨了一下这个问题,和大家分享一下. 创建maven工程,引入spring的依赖包,配置好appli ...
-
kali2.0下配置Metasploit+postgresql链接
工具/原料 kali2.0 方法/步骤 1.postgresql是本身没有启动的.所以需要启动. service postgresql start 2.通过命令进入配置 sudo -u ...
-
项目管理理论与实践(5)——UML应用(下)
本篇文章介绍UML的相关知识.参考<UML从入门到精通> 六.状态机视图 1. 概述 状态机视图通过对类对象的生存周期建立模型来描述对象随时间变化的动态行为.状态是给定类的对象的一组属性值 ...