Animal作为基类,我们要给每种动物实例化出sound()的模块,因为Animal在实际意义上没什么好实例化的,所以设计成抽象类。
class Animal
{
public:
virtual void sound() const = 0;//后面重写的函数都必须用const修饰
};
class Cat : public Animal
{
public:
virtual void sound() const
{
cout << "喵喵" << endl;
}
};
class Dog : public Animal
{
public:
virtual void sound() const
{
cout << "汪汪" << endl;
}
};
void AnimalSound(const Animal& anm)//Animal不能实例化对象,但是可以生成指针或者引用
{
anm.sound();
}
1. 虚函数表
关于虚函数、虚函数表、虚函数表指针的关系,我们有以下说明:
虚函数和其他成员函数一样,都是存在代码段的。
可通过比较虚拟函数和一般函数的地址差距:
三个函数的地址:
打印地址可发现,Func1 Func2 Func3的位置还是很接近的,都存在代码段。
而虚表的地址不一定,比如在vs下虚表就是存在常量区的,而虚表的指针才是存在对象中的。
2. 多态原理
再来观察虚函数表的存在:
常见易错:
复习:
我们通过以下方式(指针和指针之间可以强转)得到虚表的地址:
或者再创建几个不同存储位置的变量,打印不同类型的变量地址,比较大小:
对象是在栈中,虚表被处理在常量区,虚表指针在对象中所以也在栈中,虚函数在代码段。
3. 静态多态
练习:
class Base1 { public: int _b1; };
class Base2 { public: int _b2; };
class Derive : public Base1, public Base2 { public: int _d; };
int main(){
Derive d;
Base1* p1 = &d;
Base2* p2 = &d;
Derive* p3 = &d;
return 0;
}
故选C
下列说法正确的是:
A.被virtual修饰的函数称为虚函数
B.虚函数的作用是用来实现多态
C.虚函数在类中声明和类外定义时候,都必须加虚拟关键字
D.静态虚成员函数没有this指针。
结果为1.1