虚函数到底是什么?
虚函数的实际意义就是子类的成员函数把父类成员函数改写了一下,当子类成员的地址赋给父类指针变量时,子类的成员函数也随之覆盖了父类同名的成员函数。虚函数只限于有继承关系的类之间。
与虚函数相对应的多态又是什么?
多态通俗一点来讲就是有一个函数根据不同操作对象发挥不同的功能,即见人说人话,见鬼说鬼话。那多态的重要实现工具—虚函数所实现的多态通俗来讲就是一个函数它针对于有继承关系的不同类对象发挥不同功能。
多态性介绍: 关于C++中面向对象的多态特性,这里面先给大家介绍一下。什么是多态性?多态,即多种形态。在C++中一般是这么解释的:向不同的对象发送同一个消息,不同的对象在接收时会产生不同的行为。 之前其实已经给大家有使用过了,就是成员函数的重载,或者运算符的重载等等,都算是多态性的一种体现。 举个现实中的例子,我们还拿学生来做举例:说上课了,那么不同的学生可能会走进不同的教室,上课了,有的学生上语文课,有的学生上数学课,等等。所以针对同一个上课的消息,不同的学生产生的行为是不一样的。我相信大家一定会很容易明白吧。 |
下面我们用一个例子来说明:
// 多态与虚函数.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
using namespace std;
class Cdog
{
protected:
float voice;
char *name;
public:
Cdog(float voice, char *name);
~Cdog();
virtual void Shvoice()
{
cout << "父类:" << this->name << "的音量为" << voice << endl;
}
};
Cdog::Cdog(float voice, char *name)
{
this->voice = voice;
this->name = new char[strlen(name) + 1];
memset(this->name, 0, strlen(name) + 1);
strcpy(this->name, name);
}
Cdog::~Cdog()
{
if (this->name)
{
delete[] this->name;
this->name = NULL;
cout << "调用Cdog类的析构函数释放内存" << endl;
}
}
class Cdog_golden:public Cdog
{
public:
Cdog_golden(float voice, char *name) :Cdog(voice, name) {};
~Cdog_golden()
{
cout << "调用子类的析构函数" << endl;
};
void Shvoice()
{
cout << "子类:" << name << "的音量为" << voice << endl;
}
};
int main()
{
char str[] = "金毛";
Cdog_golden Gdog(67, str);
Cdog *Dog = &Gdog;
Dog->Shvoice();
}
在这里我们父类的成员函数Shvoice()声明为virtual类型,这里的含义是当我们用父类指针指向子类成员对象时,指针指向的Shvoice()其实是子类的,而非父类。
结果是:
有些同学就会疑问:
因为在父类中父类Shvoice()的优先级高于子类的Shvoice()的优先级,因此父类的指针指向的Shvoice()函数不应该时父类的吗?这就体现了virtual虚函数声明标志的作用——屏蔽功能。
Virtual的意义是当父类指针访问子类对象时,自动将父类中的同名成员函数屏蔽掉,因为继承的作用是在原始类的基础上发展更新,屏蔽掉父类的低级功能使用子类中所声明的更高级的成员函数是我们都想要的,想使用的,因此只要将父类的成员函数声明为virtual之后,用指向子类对象的指针指向该成员函数时,都会采用子类同名成员函数中更高级的处理方式。
我们再试试下面不加virtual的情况:
// 多态与虚函数.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
using namespace std;
class Cdog
{
protected:
float voice;
char *name;
public:
Cdog(float voice, char *name);
~Cdog();
void Shvoice()
{
cout << "父类:" << this->name << "的音量为" << voice << endl;
}
};
Cdog::Cdog(float voice, char *name)
{
this->voice = voice;
this->name = new char[strlen(name) + 1];
memset(this->name, 0, strlen(name) + 1);
strcpy(this->name, name);
}
Cdog::~Cdog()
{
if (this->name)
{
delete[] this->name;
this->name = NULL;
cout << "调用Cdog类的析构函数释放内存" << endl;
}
}
class Cdog_golden:public Cdog
{
public:
Cdog_golden(float voice, char *name) :Cdog(voice, name) {};
~Cdog_golden()
{
cout << "调用子类的析构函数" << endl;
};
void Shvoice()
{
cout << "子类:" << name << "的音量为" << voice << endl;
}
};
int main()
{
char str[] = "金毛";
Cdog_golden Gdog(67, str);
Cdog *Dog = &Gdog;
Dog->Shvoice();
}
结果是:
我们看到如果不对父类中的同名函数声明为virtual类型,那就会默认访问父类的成员函数。因为在父类中父类成员函数的地位高于其他类的成员函数,那么父类指针就理所当然地访问在父类内优先级最高的成员函数。