虚函数和纯虚函数

虚函数-纯虚函数区别

1
2
3
1. 虚函数允许派生类根据自己的需要重写基类的行为。在基类中,你通过在函数声明前加上virtual关键字来声明虚函数。
2. 纯虚函数(Pure Virtual Function)
纯虚函数是一种特殊的虚函数,你无法为其提供实现,而是在其声明时将其初始化为0。声明一个或多个纯虚函数的类称为抽象类(Abstract Class),你不能创建抽象类的实例。纯虚函数的目的是强制派生类提供自己的实现。

在C++中,成员函数的重写(override)是多态的一个核心概念,它允许派生类改变基类中某个函数的行为。对于虚函数来说,派生类确实可以直接重写基类中的虚函数。但是,对于非虚函数,派生类也可以提供自己的实现,这通常被称为隐藏(hiding)而不是重写。

我们来区分一下:

  1. 函数隐藏(Function Hiding):如果派生类声明了一个和基类同名的成员函数(即使参数列表不同),它将隐藏所有基类中具有相同名称的成员函数。在派生类的对象中调用这个函数时,只有派生类的版本可见,基类的版本被隐藏了。
  2. 函数重写(Function Overriding):仅当派生类中的函数与基类中的虚函数有相同的签名(函数名、参数列表、const属性等)时,才称之为重写。在派生类的对象上调用这样的函数时,将使用动态绑定,根据对象的实际类型调用相应类的函数实现。

以下是一个例子来详细说明这两种情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Base {
public:
void func() {
cout << "Base func" << endl;
}
virtual void vFunc() {
cout << "Base vFunc" << endl;
}
};

class Derived : public Base {
public:
// 函数隐藏,即使参数不同也会隐藏基类的所有同名函数
void func(int) {
cout << "Derived func with int parameter" << endl;
}
// 函数重写,因为vFunc在基类中被声明为虚函数
void vFunc() override {
cout << "Derived vFunc" << endl;
}
};

int main() {
Derived d;
d.func(10); // 调用Derived中的func,基类的func被隐藏
// d.func(); // 错误!基类的func被隐藏了,即使没有参数也不能调用
d.vFunc(); // 调用Derived中的vFunc,重写了基类的虚函数

Base* b = &d;
b->vFunc(); // 虚函数重写,调用Derived中的vFunc
return 0;
}

在这个例子中,Derived::func(int)隐藏了Base::func(),所以即使没有参数提供,你也不能通过Derived的对象来调用Base::func()。另一方面,Derived::vFunc()重写了Base::vFunc(),因此使用指向Derived对象的基类指针调用vFunc()时,将调用Derived的实现。