虚函数在 c++ 的继承体系中是一个非常重要概念,让我们可以在子类中复写父类的方法。学到这里我还不知道在 c++ 中是否有抽象类的概念,那么学习过虚函数我们就知道通过(纯)虚函数可以实现 java 中的抽象类,随后介绍。
上代码通过代码进行解释。
#include <iostream>
#include <string>
class Shape
{
public:
std::string GetName() { return "Shap"; }
};
class Rect : public Shape
{
private:
std::string m_Name;
public:
Rect(const std::string &name) : m_Name(name) {}
std::string GetName() { return m_Name; }
};
int main(int argc, char const *argv[])
{
Shape *s = new Shape();
std::cout << s->GetName() << std::endl;
Rect *r = new Rect("rectangle");
std::cout << r->GetName() << std::endl;
std::cin.get();
}
这里分别定义了 Shape
和Rect
两个类,并且Rect
继承了Shape
,同时这两个类中都有GetName()
方法。
Shap
rectangle
分别调用Shape
的实例s
和Rect
的实例·r
的 GetName
输出如上,正确无误,是我们想要的效果。
class Rect : public Shape
{
private:
std::string m_Name;
public:
Rect(const std::string &name) : m_Name(name) {}
std::string GetName() { return m_Name; }
};
int main(int argc, char const *argv[])
{
Shape *s = new Shape();
std::cout << s->GetName() << std::endl;
Shape *r = new Rect("rectangle");
std::cout << r->GetName() << std::endl;
std::cin.get();
}
向上转型后发现 Rect 实例 r 的 GetName 输出为 Shap 而不是 rectangle 。
Shap
Shap
void PrintName(Shape *s)
{
std::cout << s->GetName() << std::endl;
}
int main(int argc, char const *argv[])
{
Shape *s = new Shape();
// std::cout << s->GetName() << std::endl;
Shape *r = new Rect("rectangle");
// std::cout << r->GetName() << std::endl;
PrintName(s);
PrintName(r);
std::cin.get();
}
这里一下代码,让代码容易被理解和阅读,这里函数PrintName
接收Shape
的引用作为参数。
为什么发生这样问题,其实也很好理解,我们定义函数PrintName
接收Shape
类型的引用做为参数,所以当调用GetName
方法时候就会从Shape
类型中查找是否存在该方法然后将其调用。
要想让Rect
调用自己的的getName
方法而非其父类的GetName
的方法,就需要使用到虚函数,虚函数会根据Vtable来进行方法调用分配,这样我们就可以根据类型调用到自己的方法。
现在简单介绍一下,随后会深入介绍虚函数
class Shape
{
public:
virtual std::string GetName() { return "Shap"; }
};
class Rect : public Shape
{
private:
std::string m_Name;
public:
Rect(const std::string &name) : m_Name(name) {}
std::string GetName() override { return m_Name; }
};
要实现虚函数需要两个步骤进行修改
- 在父类中,在函数
GetName()
前面加上virtual
- 在子类中,在函数
GetName()
后面加上override
再次运行编译运行程序就得到我们想要结果了
Shap
rectangle