来看代码
我们来看看早绑定的代码
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Animal
{
public:
void speak()
{
cout << "动物在说话 " << endl;
}
};
class Cat : public Animal
{
public:
void speak() {
cout << "小猫在说话 " << endl;
}
};
// 地址早绑定,在编译阶段确定函数地址
// 如果想要执行让猫进行说话,那么这个函数地址就不能提早绑定,需要在运行阶段进行绑定
void test01() {
Cat cat;
Animal* p = &cat;
p->speak();
}
int main()
{
test01();
return 0;
}
我们需要利用到虚函数来解决问题
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Animal
{
public:
virtual void speak()
{
cout << "动物在说话 " << endl;
}
};
class Cat : public Animal
{
public:
void speak() {
cout << "小猫在说话 " << endl;
}
};
class Dog : public Animal {
public:
void speak() {
cout << "小狗在说话 " << endl;
}
};
// 地址早绑定,在编译阶段确定函数地址
// 如果想要执行让猫进行说话,那么这个函数地址就不能提早绑定,需要在运行阶段进行绑定
void test01() {
Cat cat;
Animal* p = &cat;
p->speak();
Dog dog;
Animal* pp = &dog;
p->speak();
}
// 要有继承关系
// 子类要重写父类的虚函数 , 重写 是 函数返回值 ,名称 和函数都相同
// 子类中 virtual 可写可不写
// 用父类 来 指向 子类对象
int main()
{
test01();
return 0;
}
解析一下原理
我们来看看Animal 这个类占了多少内存
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Animal
{
public:
void speak()
{
cout << "动物在说话 " << endl;
}
};
class Cat : public Animal
{
public:
void speak() {
cout << "小猫在说话 " << endl;
}
};
class Dog : public Animal {
public:
void speak() {
cout << "小狗在说话 " << endl;
}
};
// 地址早绑定,在编译阶段确定函数地址
// 如果想要执行让猫进行说话,那么这个函数地址就不能提早绑定,需要在运行阶段进行绑定
void test01() {
Cat cat;
Animal* p = &cat;
p->speak();
Dog dog;
Animal* pp = &dog;
p->speak();
}
void test02() {
cout << "Animal 这个类占的空间为 :" << sizeof(Animal) << endl; // 空类占的内存为 1
}
int main()
{
test02();
return 0;
}
显示的结果 是占了 一个字节的内存
如果这个类含有虚函数呢 , 在 vs 2019 x86 下显示的是 4 个字节, 里面会含有一个 vfptr , 虚函数指针