在C++中,virtual
是一个关键字,用于声明类的虚函数(virtual function)。虚函数是一种特殊的成员函数,允许在派生类中重写(override)基类的同名函数,并实现运行时多态性。
虚函数的基本概念
1.基本定义:使用 virtual
关键字声明的成员函数称为虚函数。例如:
class Base {
public:
virtual void show() {
cout << "Base class show() function\n";
}
};
2.多态性:虚函数允许基类指针(或引用)在运行时确定调用的是基类的函数还是派生类的函数,从而实现多态性。例如:
#include <iostream>
using namespace std;
// 基类 Animal
class Animal {
public:
// 虚函数,用于发出声音
virtual void makeSound() {
cout << "Animal makes a sound\n";
}
};
// 派生类 Dog
class Dog : public Animal {
public:
// 重写基类的虚函数,狗会吠
void makeSound() override {
cout << "Dog barks\n";
}
};
// 派生类 Cat
class Cat : public Animal {
public:
// 重写基类的虚函数,猫会喵
void makeSound() override {
cout << "Cat meows\n";
}
};
int main() {
Animal* ptr; // 基类指针
Dog d;
Cat c;
ptr = &d; // 指向派生类对象 Dog
ptr->makeSound(); // 调用派生类 Dog 的 makeSound()
ptr = &c; // 指向派生类对象 Cat
ptr->makeSound(); // 调用派生类 Cat 的 makeSound()
return 0;
}
代码解释
-
类的定义:
Animal
类是一个基类,其中定义了一个虚函数makeSound()
,用于发出声音。这个函数在基类中有一个默认实现。Dog
类和Cat
类分别是Animal
类的派生类,它们通过重写makeSound()
函数来实现狗吠和猫喵的声音。
-
虚函数和多态:
makeSound()
函数在Animal
类中被声明为虚函数,这意味着它可以在派生类中被重写,并且可以在运行时根据对象的实际类型来调用正确的版本。- 在
main()
函数中,我们声明了一个Animal*
类型的指针ptr
,并且通过将它指向不同的派生类对象来演示多态性。
-
运行结果:
- 当
ptr
指向Dog
类对象时,调用ptr->makeSound()
会输出Dog barks
。 - 当
ptr
指向Cat
类对象时,调用ptr->makeSound()
会输出Cat meows
。
- 当
这种行为展示了多态性的核心概念:通过基类指针或引用调用虚函数,实际执行的是指针或引用所指向的对象的函数版本。这种动态绑定在运行时确定调用的函数,使得代码更加灵活和可扩展。
3.派生类中的重写:派生类可以通过重写(override)基类的虚函数来提供特定实现。重写函数必须与基类的虚函数具有相同的签名(函数名和参数列表)。例如:
class Derived : public Base {
public:
void show() override {
cout << "Derived class show() function\n";
}
};
4.非虚函数:如果不使用 virtual
关键字声明函数,则该函数在派生类中重写时不会产生多态行为,而是静态绑定到基类的函数。例如:
#include <iostream>
using namespace std;
class Animal {
public:
void makeSound() {
cout << "Animal makes a sound\n";
}
};
class Dog : public Animal {
public:
void makeSound() {
cout << "Dog barks\n";
}
};
class Cat : public Animal {
public:
void makeSound() {
cout << "Cat meows\n";
}
};
int main() {
Animal* animalPtr;
Dog dog;
Cat cat;
animalPtr = &dog;
animalPtr->makeSound(); // 调用的是基类的 makeSound() 函数,输出: Animal makes a sound
animalPtr = &cat;
animalPtr->makeSound(); // 调用的是基类的 makeSound() 函数,输出: Animal makes a sound
return 0;
}
5.纯虚函数:可以使用 virtual
关键字声明一个纯虚函数,没有函数体,类似于接口,要求派生类必须实现该函数。例如:
class Shape {
public:
virtual void draw() = 0; // 纯虚函数声明
};
使用 virtual
的场景
- 当希望在基类和派生类中提供不同的实现时,使用虚函数可以实现运行时的多态性。
- 虚函数在实现多层次的继承结构时非常有用,可以确保在正确的上下文中调用适当的函数实现。
总之,virtual
关键字是实现面向对象编程中多态性的关键,通过它可以在继承层次结构中进行动态绑定,从而提供灵活和可扩展的代码结构。