虚函数
- C++中的多态通过虚函数(virtual function)来实现
- 虚函数:被virtual修饰的成员函数
- 只要在父类中声明为虚函数,子类中重写的函数也自动变成虚函数(也就是说子类中可以省略virtual关键字)
虚表
虚函数的实现原理是虚表,这个虚表里面存储着最终需要调用的虚函数地址,这个虚表也叫虚函数表
class Animal {
public:
int m_age;
virtual void speak() {
cout << "Animal::speak()" << endl;
}
virtual void run() {
cout << "Animal::run()" << endl;
}
};
class Cat : public Animal {
public:
int m_life;
Cat() :m_life(0) {}
void speak() {
cout << "Cat::speak()" << endl;
}
void run() {
cout << "Cat::run()" << endl;
}
};
虚表(x86环境的图)
所有的Cat对象(不管在全局区、栈、堆)共用同一份虚表
思考:如果子类没有重写父类的虚函数,那么子类还有虚表吗?
class Animal {
public:
int m_age;
virtual void speak() {
cout << "Animal::speak()" << endl;
}
virtual void run() {
cout << "Animal::run()" << endl;
}
};
class Cat : public Animal {
public:
int m_life;
Cat() :m_life(0) {}
};
答案:有,可以使用sizeof打印Cat
对象的大小
思考:子类重写父类的虚函数,先执行父类中的成员函数,再执行自己的一些操作?
class Animal {
public:
int m_age;
virtual void speak() {
cout << "Animal::speak()" << endl;
}
virtual void run() {
cout << "Animal::run()" << endl;
}
};
class Cat : public Animal {
public:
int m_life;
Cat() :m_life(0) {}
void speak() {
// 先执行父类中的成员函数
Animal::speak();
// 再执行自己的一些操作
cout << "Cat::speak()" << endl;
}
void run() {
cout << "Cat::run()" << endl;
}
};
int main() {
Animal *animal2 = new Cat();
animal2->speak();
animal2->run();
getchar();
return 0;
}
虚析构函数
含有虚函数的类,应该将析构函数声明为虚函数(虚析构函数),一般只需要在父类声明
virtual
即可
delete父类指针时,才会调用子类的析构函数,保证析构的完整性
class Animal {
public:
int m_age;
virtual void speak() {
cout << "Animal::speak()" << endl;
}
virtual void run() {
cout << "Animal::run()" << endl;
}
virtual ~Animal() {
cout << "~Animal()" << endl;
}
};
class Cat : public Animal {
public:
int m_life;
Cat() :m_life(0) {}
void speak() {
cout << "Cat::speak()" << endl;
}
void run() {
cout << "Cat::run()" << endl;
}
~Cat() {
cout << "~Cat()" << endl;
}
};
思考:如果父类的析构函数不声明为虚析构函数,那么会出现什么情况?
int main() {
Animal *cat1 = new Cat();
cat1->speak();
cat1->run();
delete cat1;
getchar();
return 0;
}
如上代码,子类的析构函数~Cat()
不会调用