📅  最后修改于: 2023-12-03 15:29:52.071000             🧑  作者: Mango
在 C++ 中,虚函数是一种非常有用的概念。它们可以帮助我们实现多态性,即让子类对象表现出与父类不同的行为。但是,在使用虚函数时,我们可能会遇到问题。本文将介绍 C++ 中虚函数可能遇到的一些问题以及解决方法。
基类 Animal 有一个虚函数 speak()
,两个子类 Cat 和 Dog 分别重写这个函数。现在我们用一个指向 Animal 的指针变量调用 speak()
,但是它调用的是基类 Animal 的 speak()
函数,而不是子类的。为什么会出现这种情况,该如何解决呢?
#include <iostream>
class Animal {
public:
virtual void speak() {
std::cout << "Animal speak." << std::endl;
}
};
class Cat : public Animal {
public:
void speak() {
std::cout << "Cat speak." << std::endl;
}
};
class Dog : public Animal {
public:
void speak() {
std::cout << "Dog speak." << std::endl;
}
};
int main() {
Animal* a = new Cat();
a->speak(); // 输出 "Animal speak."
return 0;
}
问题在于,当使用一个指向派生类对象的基类指针或引用调用虚函数时,该指针或引用不知道它们指向的到底是基类还是派生类,因此它们只会调用基类的虚函数。
在上面的代码中,Animal* a = new Cat();
创建了一个 Cat 的对象,并且使用基类 Animal 的指针 a 指向该对象。调用 a->speak()
时,由于 speak()
是虚函数,编译器将自动解析出适当的函数调用。但是,由于 a 是基类 Animal 的指针,编译器只会找到基类的 speak()
函数。
要解决这个问题,我们需要在派生类的函数前加上 virtual
关键字。这样,当使用基类指针或引用调用函数时,编译器会检查实际指向的对象的类型,并选择正确的函数。
class Animal {
public:
virtual void speak() {
std::cout << "Animal speak." << std::endl;
}
};
class Cat : public Animal {
public:
virtual void speak() {
std::cout << "Cat speak." << std::endl;
}
};
class Dog : public Animal {
public:
virtual void speak() {
std::cout << "Dog speak." << std::endl;
}
};
int main() {
Animal* a = new Cat();
a->speak(); // 输出 "Cat speak."
return 0;
}
虚函数是实现多态性的重要工具,但在使用时可能会出现问题。当使用基类指针或引用调用虚函数时,如果没有在派生类中将函数声明为虚函数,可能会调用基类的函数。为了避免这个问题,必须确保在派生类中将函数声明为虚函数。