目录
建议看下面的内容之前,先看一下c++特性之多态
这里我们先来看一个笔试题:请问 sizeof(Base)是多少?
class Base
{
public:
virtual void Func1()
{
cout << "Func1()" << endl;
}
private:
int _b = 1;
};
答案是:8? ?为什么呢?按照内存对齐的规则,这里应该是4byte,为什么是8byte呢?
调试一下:
构成多态的两个条件:
1. 虚函数的重写 ?--- 三同(函数名,参数,返回值)?
? ? a.例外(协变):返回值可以不同,必须是父子关系指针或者引用
? ? b.子类虚函数可以不加virtual
2. 必须是基类指针或者引用调用虚函数
a.不满足多态 --- 看调用者的类型,调用这个类型的成员函数
b.满足多态 --- ? 看指向对象的类型,调用这个类型的成员函数 ?
示例:
// 针对上面的代码我们做出以下改造
// 1.我们增加一个派生类Derive去继承Base
// 2.Derive中重写Func1
// 3.Base再增加一个虚函数Func2和一个普通函数Func3
class Base
{
public:
virtual void Func1()
{
cout << "Base::Func1()" << endl;
}
virtual void Func2()
{
cout << "Base::Func2()" << endl;
}
void Func3()
{
cout << "Base::Func3()" << endl;
}
private:
int _b = 1;
};
class Derive : public Base
{
public:
virtual void Func1()
{
cout << "Derive::Func1()" << endl;
}
private:
int _d = 2;
};
int main()
{
Base b;
Derive d;
return 0;
}
调试:
class Person
{
public:
virtual void BuyTicket() { cout << "买票-全价" << endl; }
};
class Student : public Person
{
public:
virtual void BuyTicket() { cout << "买票-半价" << endl; }
};
void Func(Person& p)
{
p.BuyTicket();
}
int main()
{
Person Mike;
Func(Mike);
Student Johnson;
Func(Johnson);
return 0;
}
示例:
class Base{
public:
virtual void Func1(){cout << "Base::Func1()" << endl;}
virtual void Func2(){cout << "Base::Func2()" << endl;}
void Func3(){cout << "Base::Func3()" << endl;}
};
class Derive : public Base{
public:
virtual void Func1(){cout << "Derive::Func1()" << endl;}
virtual void Func4(){cout << "Derive::Func4()" << endl;}
};
//打印虚表 vf:virtual function table:一览表
//注意:( vs系列 ) 虚函数表本质是一个存虚函数指针的指针数组
// 一般情况这个数组最后面放了一个nullptr。( g++没有 )
typedef void(*VF_PTR)() ;
void print_vf_table(VF_PTR table[])
{
for (int i = 0; table[i] != nullptr; ++i)
{
printf("[%d]: %p -> ",i, table[i]);
VF_PTR f = table[i];
f();
}
cout << endl;
}
int main()
{
Base b;
Derive d;
print_vf_table((VF_PTR*)(*(int*)&b));
print_vf_table((VF_PTR*)(*(int*)&d));
//虚表是在什么阶段生成的呢? - 编译
//对象中的虚表指针是在什么时候进行初始化的呢? - 构造函数(初始化列表)
//虚表存储在什么地方? - 代码段(常量区)
//print_vf_table((*(VF_PTR**)&b));
//print_vf_table((*(VF_PTR**)&d));
return 0;
}
class base1 {
public:
virtual void func1() { cout << "base1::func1" << endl; }
virtual void func2() { cout << "base1::func2" << endl; }
private:
int b1;
};
class base2 {
public:
virtual void func1() { cout << "base2::func1" << endl; }
virtual void func2() { cout << "base2::func2" << endl; }
private:
int b2;
};
//base1 , base2各自有两个虚函数
//derive多继承base1,base2
//重写虚函数 func1()
//新增虚函数func3()
class derive : public base1, public base2 {
public:
virtual void func1() { cout << "derive::func1" << endl; }
virtual void func3() { cout << "derive::func3" << endl; }
private:
int d1;
};
问题1:derive一共会生成几张虚表?
问题2:func3()会放进哪张虚表,还是所有虚表都会放进去?
调试一下:
????????好像只生成了两张虚表,没看到func3().这样,我们再打印一下虚表看一下,但是这里遇到一个问题,第一张虚表指针刚好指向对象的头四个字节,怎样取到第二张虚表表指针?