C++中继承与多态的基础虚函数类详解
|
我们来使用这个函数,该函数代码如下:
//单继承
class Base
{
public:
virtual void func1()
{
cout << "Base::func1" << endl;
}
virtual void func2()
{
cout << "Base::func2" << endl;
}
private:
int a;
};
class Derive :public Base
{
public:
virtual void func1()
{
cout << "Derive::func1" << endl;
}
virtual void func3()
{
cout << "Derive::func3" << endl;
}
virtual void func4()
{
cout << "Derive::func4" << endl;
}
private:
int b;
};
typedef void(*FUNC)(void);
void PrintVTable(int* VTable)
{
cout<< " 虚表地址"<<VTable<< endl;
for(inti = 0;VTable[i] != 0; ++i)
{
printf(" 第%d个虚函数地址 :0X%x,VTable[i]);
FUNC f = (FUNC)VTable[i];
f();
}
cout<< endl;
}
int main()
{
Derive d1;
PrintVTable((int*)(*(int*)(&d1))); //重点
system("pause");
return0;
}
这里我就要讲讲这个传参了,注意这里的传参不好理解,应当细细的"品味". PrintVTable((int*)(*(int*)(&d1))); 首先我们肯定要拿到d1的首地址,把它强转成int*,让他读取到前4个字节的内容(也就是指向虚表的地址),再然后对那个地址解引用,我们已经拿到虚表的首地址的内容(虚表里面存储的第一个函数的地址)了,但是此时这个变量的类型解引用后是int,不能够传入函数,所以我们再对他进行一个int*的强制类型转换,这样我们就传入参数了,开始函数执行了,我们一切都是在可控的情况下使用强转,使用强转你必须要特别清楚的知道内存的分布结构。 最后我们来看看输出结果:
到底打印的对不对呢? 我们验证一下:
这里我们通过&d1的首地址找到虚表的地址,然后访问地址查看虚表的内容,验证我们自己写的这个函数是正确的。(这里VS还有一个bug,当你第一次打印虚表时程序可能会崩溃,不要担心你重新生成解决方案,再运行一次就可以了。因为当你第一次打印是你虚表最后一个地方可能没有放0,所以你就有可能停不下来然后崩溃。)我们可以看到d1的虚表并不是监视器里面打印的那个样子的,所以有时候VS也会有bug,不要太相信别人,还是自己靠得住。哈哈哈,臭美一下~ 我们来研究一下多继承的内存格局 探究完了单继承,我们来看看多继承,我们还是通过代码调试的方法来探究对象模型 看如下代码:
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;
};
class Derive : public Base1,public Base2
{
public:
virtual void func1()
{
cout << "Derive::func1" << endl;
}
virtual void func3()
{
cout << "Derive::func3" << endl;
}
private:
int d1;
};
typedef void(*FUNC) ();
void PrintVTable(int* VTable)
{
cout << " 虚表地址>" << VTable << endl;
for (int i = 0; VTable[i] != 0; ++i)
{
printf(" 第%d个虚函数地址 :0X%x,VTable[i]);
FUNC f = (FUNC)VTable[i];
f();
}
cout << endl;
}
void Test1()
{
Derive d1;
//Base2虚函数表在对象Base1后面
int* VTable = (int*)(*(int*)&d1);
PrintVTable(VTable);
int* VTable2 = (int *)(*((int*)&d1 + sizeof (Base1) / 4));
PrintVTable(VTable2);
}
int main()
{
Test1();
system("pause");
return 0;
}
现在我们现在知道会有两个虚函数表,分别是Base1和Base2的虚函数表,但是呢!我们的子类里的
(编辑:泰州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |





