当类中声明虚函数时,编译器会在类中生成一个虚函数表
虚函数表是一个存储类成员函数指针的数据结构
#include<iostream>
using namespace std;
// 多态成立三条件
// 继承 虚函数重写 父类指针指向子类
class Parent {
public:
Parent(int a = 0) {
this->a = a;
}
virtual void print() { // virtual 放入虚函数表
cout << "Parent" << endl;
}
private:
int a;
};
class Child : public Parent {
public:
Child(int a = 0, int b =0):Parent(a) {
this->b = b;
}
virtual void print() {
cout << "Child" << endl;
}
private:
int b;
};
void play(Parent* base) {
base->print(); // 多态 传父类执行父类成员函数;传子类执行子类成员函数
// 父类对象和子类对象分别有vptr指针,找虚函数表,再找函数的入口
}
void main() {
Parent p1; //用类定义对象 c++编译器会在对象中添加vptr指针
// 提前布局
Child c1; // vptr指针
play(&p1);
play(&c1);
}
加virtual多4个字节,证明vptr指针的存在?
// 证明vptr指针
class Parent1 {
public:
Parent1(int a = 0) {
this->a = a;
}
void print() { // virtual 放入虚函数表
cout << "Parent" << endl;
}
private:
int a;
};
class Parent2 {
public:
Parent2(int a = 0) {
this->a = a;
}
virtual void print() { // virtual 放入虚函数表
cout << "Parent" << endl;
}
private:
int a;
};
void main() {
cout << "sizeof(Parent1):" << sizeof(Parent1) << endl;
cout << "sizeof(Parent2):" << sizeof(Parent2) << endl;
}
结果
sizeof(Parent1):4
sizeof(Parent2):8
1 构造函数中调用虚函数能实现多态吗?
// 构造函数中调用虚函数能多态吗
class Parent {
public:
Parent(int a = 0) {
this->a = a;
print();
}
virtual void print() { // virtual 放入虚函数表
cout << "Parent" << endl;
}
private:
int a;
};
class Child : public Parent {
public:
Child(int a = 0, int b =0):Parent(a) {
this->b = b;
print();
}
virtual void print() {
cout << "Child" << endl;
}
private:
int b;
};
void main() {
Child c1; // 创建子类对象,父类过程中print虚函数能发生多态吗?(不会)
}
案例:父类指针和子类指针的步长
父类指针和子类指针++步长不是一个概念
// 父类指针和子类指针的步长
class Parent {
public:
Parent(int a = 0) {
this->a = a;
}
virtual void print() { // virtual 放入虚函数表
cout << "Parent" << endl;
}
private:
int a;
};
class Child : public Parent {
public:
Child(int b =0):Parent(0) {
// this->b = b;
}
virtual void print() {
cout << "Child" << endl;
}
private:
int b;
};
void main() {
Child c1;
Parent* pP = NULL;
Child* pC = NULL;
Child array[] = { Child(1),Child(2), Child(3) };
pP = array;
pC = array;
pP->print(); // 此时 pP地址为0x0093f760
pC->print(); // pC 0x0093f760
pP++; // 0x0093f768 4个字节(int a)+virtual
pC++; // 0x0093f76C 8(int a)(int b) + virtual
//pP->print(); 这是会报错
pC->print();
}