虚函数定义
所谓虚函数就是在基类定义一个未实现的函数名,为了提高程序的可读性,虚函数都加上virtual关键字。一般格式:
class base
{
public:
base();
virtual void test(); //定义的一个虚函数
private:
char *basePStr;
};
虚函数存在的意义:实现C++的多态。
虚函数使用的其核心目的是通过基类访问派生类定义的函数。
上述代码在基类中定义了一个test的虚函数,所有可以在其子类重新定义父类的做法这种行为成为覆盖(override),或者为重写。
#include<iostream>
using namespace std;
class A
{
public:
void foo()
{
printf("1\n");
}
virtual void fun()
{
printf("2\n");
}
};
class B : public A
{
public:
void foo() //隐藏:派生类的函数屏蔽了与其同名的基类函数
{
printf("3\n");
}
void fun() //多态、覆盖
{
printf("4\n");
}
};
int main(void)
{
A a;
B b;
A *p = &a;
p->foo(); //输出1
p->fun(); //输出2
p = &b;
p->foo(); //取决于指针类型,输出1
p->fun(); //取决于对象类型,输出4,体现了多态
return 0;
}
虚函数的常见错误
无意的重写
无意的重写 示例如下,在派生类中声明了一个与基类的某个虚函数具有相同的签名的成员函数,不小心重写了这个虚函数。
class Base {
public:
virtual void Show(); // 虚函数
};
class Derived : public Base {
public:
void Show(); // 无意的重写
};
虚函数签名不匹配
函数的签名包括:函数名,参数列表,const属性。
虚函数签名不匹配的错误通常是因为 函数名、参数列表 或 const 属性不一样,导致意外创建了一个新的虚函数,而不是重写一个已存在的虚函数。
class Base {
public:
virtual void Show(int x); // 虚函数
};
class Derived : public Base {
public:
virtual void Sh0w(int x); // o 写成了 0,新的虚函数
virtual void Show(double x); // 参数列表不一样,新的虚函数
virtual void Show(int x) const; // const 属性不一样,新的虚函数
};
上述三种写法,编译器并不会报错,因为它不知道你的目的是重写虚函数,而是把它当成了新的虚函数。
注意:虚函数的继承是永久性的,也就是说父类声明某个函数为虚函数,在孙子类,孙子孙子类中也还是虚函数,仍然可以实现动态多态:根据实际指向的类型来选择执行的方法。不过为了可读性和意义明确,派生类也建议加上virtual关键字。