2,777
社区成员
我是荔园微风,作为一名在IT界整整25年的老兵,今天来聊聊Visual C++中函数的覆盖和函数的隐藏。
Visual C++中函数的覆盖和函数的隐藏与JAVA有很大不同,有些容易搞错的点和概念,我们要特别注意。
首先,先满足一下急性子的同学,因为有的同学是因为急于了解虚函数和纯虚函数才来看这篇帖子的,那你可以先这样理解:
这就是本人的学习方法和别人不一样的地方,我年轻时学C++始终不得要领,于是我把JAVA学会后再去学C++,就全都搞明白了。所以我的帖子都是用这种方法去学C++的。希望那些学C++很吃力的同学可以来借鉴我的这个学习方法。
好了,我们先来看一个程序,一个父亲和一个儿子,希望父亲的学习本领能被儿子继承下去。我们在儿子类中重新定义学习方法。我们希望如果对象是儿子,就调用 儿子类的学习方法,如果对象是父亲,那么就调用父亲类的学习方法。
#include <iostream>
using namespace std;
class Father
{
public:
void eat()
{
cout<<"eat"<<endl;
}
void run()
{
cout<<"run"<<endl;
}
virtual void study()
{
cout<<"study"<<endl;
}
};
class Son : public Father
{
public:
void study()
{
cout<<"new study"<<endl;
}
};
void fn(Father *p)
{
p->study();
}
int main()
{
Father *p;
Son boy;
p=&boy;
fn(p);
return 0;
}
在基类父亲类的study函数前添加了virtual关键字,声明该函数为虚函数。在派生类儿子类中重写了 study函数,我们注意到, 儿子类的study函数和父亲类的study函数完全一样,无论是函数名,还是参数列表都是一样的,这称为函数的覆盖(override)。
我们必须知道构成函数覆盖的条件为:(1)基类函数必须是虚函数(使用 virtual关键字进行声明)。(2)发生覆盖的两个函数要分别位于派生类和基类中。(3)函数名称与参数列表必须完全相同。由于C++的多态性是通过虚函数来实现的,所以函数的覆盖总和多态关联在一起(这一点和JAVA十分相似, 但是JAVA不需要virtual这种关键词)。在函数覆盖的情况下,编译器会在运行时根据对象的实际类型来确定要调用的函数。
我们再看代码:
#include <iostream>
using namespace std;
class Father
{
public:
void eat()
{
cout<<"eat"<<endl;
}
void run()
{
cout<<"run"<<endl;
}
void study()
{
cout<<"study"<<endl;
}
};
class Son : public Father
{
public:
void study()
{
cout<<"new study"<<endl;
}
};
void fn(Father *p)
{
p->study();
}
int main()
{
Father *p;
Son boy;
p=&boy;
fn(p);
return 0;
}
这个其实又回到我之前一个帖子的内容了,大家有兴趣可以看看那个帖子:
大家应该可以看出来这段代码前面代码的区别。在这段代码中,派生类儿子类中的study函数和基类父亲类中的study函数是完全一样的,不同的是study函数不是虚函数,这种情况称为函数的隐藏。所谓隐藏,是指派生类中具有与基类同名的函数(不考虑参数列表是否相同),从而在派生类中隐藏了基类的同名函数。
初学VC者很容易把函数的隐藏与函数的覆盖、重载相混淆,我们看下面两种函数隐藏的情况:
下面我们给出一个例子,以帮助大家加深理解函数的覆盖和隐藏
class Father
{
public:
virtual void fn();
};
class Son:public Father
{
public:
void fn(int);
};
class Grandson:public Son
{
public:
void fn();
};
在上面代码中, 儿子类的 fn(int)函数隐藏了父亲类的fn()函数, 儿子类 fn(int)函数不是虚函数(注意和覆盖相区别)。 孙子类的 fn()函数隐藏了 儿子类的 fn(int)函数,由于 孙子类的 fn()函数与 父亲类的fn()函数具有同样的函数名和参数列表,因此 孙子类的 fn()函数是一个虚函数,覆盖了父亲 类的 fn()函数。注意,在孙子类中, 父亲类的 fn()函数是不可见的,但这并不影响 fn 函数的覆盖。
当隐藏发生时,如果在派生类的同名函数中想要调用基类的被隐藏函数,那么可以使用“基类名::函数名(参数)”的语法形式。例如,要在儿子类的fn(int)方法中调用父亲类的fn()方法,可以使用Father::fn()语句。
有的初学者可能会想,怎样才能更好地区分覆盖和隐藏呢?实际上只要记住一点:
文章来源: https://blog.csdn.net/wang2015cn/article/details/131451739
版权声明: 本文为博主原创文章,遵循CC 4.0 BY-SA 知识共享协议,转载请附上原文出处链接和本声明。