虚函数问题探讨

时间:2021-12-28 18:38:44

刚学c++的时候就觉得虚函数有点难懂,这次又碰到了,所以想搞搞懂,所以花了点时间。觉得应该记下来,下次方便看

代码:

#include <iostream>

using namespace std;

class Base
{
private:
int num;
char *name;
public:
Base() {};
virtual ~Base() { cout << "destructor of class base!" << endl; };
void Set() { num = 1; name = "name"; };
virtual void Dosomething()
{
cout << "Do smoething in class Base!" << endl;
}
};

class Derived :public Base
{
private:
int id;
public:
Derived() {};
~Derived() { cout << "destructor of class derived!" << endl; };
void Set() { id = 1;};
void Dosomething()
{
cout << "Do smoething in class Derived!" << endl;
}
};

int main()
{
Base b;
Derived d;
Base *test = new Derived;
cout << "sizeof(Base)" << sizeof(Base) << endl;
cout << "sizeof(Derived)" << sizeof(Derived) << endl;
printf("b.addr = %p\n", &b);
printf("d.addr = %p\n", &d);
test->Dosomething();

delete  test;

system("pause");
}

虚函数问题探讨

虚函数问题探讨

不难看出存在虚函数时,创建对象的时候会产生一个虚函数表指针(_vfptr),指向对应类的虚函数表。

1.虚函数表指针就是一个二级指针(32位机占4字节,所以sizeof(Base)= 12)

2.虚函数表中存放的是虚函数的函数指针,普通函数不在里面(可以看Set函数)

3.创建对象时,对象的虚函数表指针(_vfptr)指向对应的虚函数表(对象b中的虚函数指针是指向Base中的函数,对象d中的虚函数指针指向Derived中的函数)

4.从对象d可以看出对象d中的虚函数表指针是在调用Base构造函数的时候创建的,并指向类Derived的虚函数表

5.函数表的地址是静态的从上面可以看出对象test和d中的虚函数表指针(_vfptr)都指向相同的地址

6.析构函数可以是虚函数(在delete test时调用了~Derived(),在执行Derived析构函数调用了基类的析构函数,所以打出两句话,此外看虚函数表也能看出)

**************最后来说说为什么基类指针指向子类对象会调用子类函数,实现多态性**************************************

其实看了上面的代码给分析,大家应该已经得出结论了:

对指针有多了解的人应该知道,把Derived的指针转换成Base指针时,里面内容都是不会变的,只是指针结构会发生改变,但是Derived又是Base的子类,Derived构造时继承了Base的成员num,name和_vfptr(虚函数表指针,在创建对象的时候就已经指向了Derived的虚函数表),所以除自己的成员函数之外,他们的结构是一样的,所以在Base类型的test指针调用函数Dosomething()函数时,test->_vfptr->Dosomething()。因为内容都是没有变得所以_vptr中存放的Dosomething()地址还是Derived类中的函数地址

*******************************************************************************************************************************

虚函数涉及的问题还有很多,后面碰到其他问题我会继续跟进,如果大家碰到问题也可以联系我,我非常希望能够和大家一起成长。