C++中虚函数和纯虚函数
总结一下虚函数和纯虚函数到底是个什么东西
在了解虚函数之前要知道C++继承是怎么回事儿
虚函数
废话不多说, 直接上代码:
#include <iostream>
class Base
{
public:
virtual void f(float x) { std::cout << "Base::f " << x << "\n"; }
void g(float x){ std::cout << "Base::g " << x << "\n"; }
};
class Derived : public Base
{
public:
void f(float x){ std::cout << "Derived::f " << x << "\n"; }
void g(float x){ std::cout << "Derived::g " << x << "\n"; }
};
int main(int argc, char const *argv[])
{
Derived A;
Base* pb = &A;
Derived* pd = &A;
//
std::cout << "Virtual Test:\n";
A.f(3.14);
pb->f(3.14);
pd->f(3.14);
//
std::cout << "\nNon-Virtual Test:\n";
A.g(3.14);
pb->g(3.14);
pd->g(3.14);
return 0;
}
解释一下这段代码在干啥:
- Base类定义两个函数: f, g, 两个函数的功能一模一样, 都是打印传入的x, 区别在于f是前有virtual关键字, 即f是虚函数
- Derived类继承自Base类, 定义两个函数: f, g, 两个函数的功能一模一样, 都是打印传入的x
- main函数定义了一个Derived类A, 然后分别用一个Base类的指针(小贴士: C++中基类指针可以指向派生类, 但派生类指针不能指向基类)和一个Derived类的指针指向它
- 三者统一传入参数3.14, 观察A本身和有无virtual关键字的函数打印结果对比
运行结果:
Virtual Test:
Derived::f 3.14
Derived::f 3.14
Derived::f 3.14
Non-Virtual Test:
Derived::g 3.14
Base::g 3.14
Derived::g 3.14
对比可知:
Base* pb = &A;
这个类调用的是派生类Derived中的f
和自身的g
, 也就是说虽然pb指向的是一个派生类, 但是由于pb自己有明确的函数g的实现,
于是就会覆盖A中的实现
而使用虚函数就会避免这个问题, 虚函数相当于留了一个插槽, 如果派生类中有实现了基类中的虚函数, 则直接调用派生类中最早的实现
纯虚函数
纯虚函数只存在于基类中, 纯虚函数的写法为在虚函数末尾加上= 0
class Base
{
virtual f(float x) = 0;
}
在写完这句声明之后, 不能有任何实现(编译器会报错的), 因为纯虚函数的意义就是给后面的派生类留一个接口
纯虚函数是在告诉程序员:"如果你想使用这个类的派生类, 你就必须在派生类中实现预留的纯虚函数!"