一、引言
在C++面向对象编程中,虚函数(Virtual Functions)和纯虚函数(Pure Virtual Functions)是两个核心概念,它们为实现多态性提供了基础。同时,函数重写(Function Overriding)是面向对象编程中子类对父类函数进行重新定义的一种技术。本文将详细探讨这些概念,包括它们的定义、用法以及在实际编程中的应用。
二、虚函数
定义
虚函数是在基类中声明并在一个或多个派生类中被重新定义的成员函数。在基类中使用virtual关键字进行声明,以表明该函数可以在派生类中被重写。
cpp
|
class Base { |
|
public: |
|
virtual void function() { |
|
// 基类实现 |
|
std::cout << "Base function called." << std::endl; |
|
} |
|
}; |
|
|
|
class Derived : public Base { |
|
public: |
|
void function() override { // override是可选的,但建议使用以提供额外的清晰度 |
|
// 派生类实现 |
|
std::cout << "Derived function called." << std::endl; |
|
} |
|
}; |
用途
虚函数的主要用途是实现多态性。通过基类指针或引用指向派生类对象,并调用虚函数时,将执行与指针或引用所指向的对象类型相对应的派生类中的函数版本。这允许在运行时动态地确定要调用的函数版本。
cpp
|
Base* ptr = new Derived(); |
|
ptr->function(); // 输出 "Derived function called." |
|
delete ptr; |
三、纯虚函数
定义
纯虚函数是在基类中声明的虚函数,但它没有定义(只有声明)。在函数声明的结尾使用= 0来指示该函数是纯虚函数。包含纯虚函数的类被称为抽象类(Abstract Class),抽象类不能被实例化。
cpp
|
class AbstractBase { |
|
public: |
|
virtual void pureVirtualFunction() = 0; // 纯虚函数 |
|
}; |
|
|
|
class Derived : public AbstractBase { |
|
public: |
|
void pureVirtualFunction() override { |
|
// 派生类实现 |
|
std::cout << "Derived pure virtual function called." << std::endl; |
|
} |
|
}; |
用途
纯虚函数用于定义接口,指定派生类必须实现的函数。通过继承抽象类并提供纯虚函数的实现,派生类可以创建具有特定行为的对象。这有助于实现代码重用和模块化设计。
四、函数重写
定义
函数重写(也称为函数覆盖)是指派生类中存在一个与基类虚函数同名、同参数列表、同返回类型的函数,并且该函数在派生类中使用override(可选)关键字进行声明。这样,当使用基类指针或引用指向派生类对象并调用该函数时,将执行派生类中的函数版本。
cpp
|
class Base { |
|
public: |
|
virtual void function() { |
|
// ... |
|
} |
|
}; |
|
|
|
class Derived : public Base { |
|
public: |
|
void function() override { // 使用override关键字 |
|
// ... |
|
} |
|
}; |
注意事项
· 派生类重写的函数必须与基类中的虚函数具有相同的名称、参数列表和返回类型(协变返回类型除外)。
· 重写函数不能具有比基类函数更严格的访问控制(例如,基类函数为public,派生类函数不能为private或protected)。
· 如果基类函数不是虚函数,派生类中的同名函数将隐藏基类函数,而不是重写它。这可能会导致意外的行为,因此应始终将打算被重写的函数声明为虚函数。
五、总结
虚函数、纯虚函数和函数重写是C++面向对象编程中的核心概念,它们为实现多态性和代码重用提供了强大的支持。通过正确地使用这些技术,我们可以创建灵活、可扩展和可维护的软件系统。在实际编程中,应根据具体需求选择是否使用虚函数和纯虚函数,并遵循函数重写的规则来确保代码的正确性和可读性。