按:一入此门深似海……
此篇仅是个人的一些理解。希望能把自己之前遇到的问题的思考和后续研究整理出来。
此诸概念在面向对象的编程范围内讨论。
重载:(overloaded)
抄百度:
重载,简单说,就是函数或者方法有相同的名称,但是参数列表不相同的情形,这样的同名不同参数的函数或者方法之间,互相称之为重载函数或者方法。
也就是说,重载,是在同一个类中,多个函数共用一个函数名,但由于其参数的不同,各函数可以准确调用。
成员函数被重载的特征:
(查阅多方资料,四点靠谱)
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。(是指在当前类里,virtual可有可无)
class A //同一个类里
{
public:
double fun(int){...} //函数名字相同,参数不同
double fun(char){...}
virtual double fun(double){...} //virtual可有可无,因为virtual必须经过继承才有作用
};
在讲覆盖之前,需要先确定一下多态和多肉的区别到底有多大。。
多态:
多态(Polymorphism)按字面的意思就是“多种状态”。
在面向对象语言中,接口的多种不同的实现方式即为多态。
引用Charlie Calverts对多态的描述:
多态性是允许你将父对象设置成为一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(摘自“Delphi4 编程技术内幕”)。
简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。多态性在Object Pascal和C++中都是通过虚函数实现的。(抄百度)
也就是说,所谓多态,就是虚函数在做的事情。
在这个意义上,来讨论重载和覆盖就容易了。
覆盖:(inheritance)
重载和多态无关,真正和多态相关的是覆盖。
当派生类重新定义了基类的虚拟成员函数后,基类根据赋给它的不同的派生类引用,动态地调用属于派生类的对应函数,这样的方法调用在编译期间是无法确定的。
因此,这样的函数地址是在运行期绑定的(动态联编)。
重载只是一种语言特性,是一种语法规则,与多态无关,与面向对象也无关。
这种“覆盖”有一个专门的名词——重写或重定义。
重载与重写的区别就在于是否覆盖,重写一般多发生在不同的类且存在继承关系之间,而重载多是在一个类里或者一块代码段里。
覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。
class A:
{
public:
virtual void A(){cout<<1;}
};
class B:public A
{
public:
virtual void A(){cout<<14548451847;} //虚函数。这叫覆盖。
};
其实,覆盖就是虚函数在追求实现的效果。
在此之外,还有一个东西,叫隐藏:
隐藏
隐藏,是指派生累函数将基类函数给藏起来了,当然只作用于派生类函数,其特性与覆盖不同。
这里“隐藏”是指派生类的函数屏蔽了与其同名的基类函数
class A:
{
public:
void A(){cout<<1;}
};
class B:public A
{
public:
void A(){cout<<14548451847;} //虚函数。这叫覆盖。
};
在最初接触继承机制时,我们知道,
在派生类中,允许再次创建和基类同名乃至函数头完全一致的新函数,(具体而言,对参数是否一样不作规定)
(而且,在教材中,这个操作被称为“在派生类中重载基类的成员函数”)
当我们在派生类的意义下调用该函数(名)时,将默认调用派生类中新增添的那个。如果想调用老的基类中的函数,要通过作用域运算符:
int main()
{
B a;
a.A(); //调用B类对象a中新增的A函数
a.A::A(); //调用B类对象a中从A类继承来的A函数
}
继承的规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。
此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
这个时候:
- 如果是没有virtual的话,无非就是最容易理解的在子类中添加了一个同名但不同参的新函数。常规操作。
- 如果是有virtual的话,可以翻上一篇文章。可知此时因为同名不同参,所以C++会认为这只是个普通的函数重载,即“失去虚特性”,会被识别为常规操作。呜呼。。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。
此时,基类的函数被隐藏(注意别与覆盖混淆)。
从讨论的范围来说:
- 重载只针对一个类,跟继承一点关系没有。
- 覆盖是在虚函数继承体系中讨论的,是派生类和基类共同存在时才有讨论价值的。
- 隐藏也是继承中出现的,但和虚继承没有太多关系。