C++之探索多态的本质(虚函数与虚表)2

我们都知道对于类中存在虚函数的时候,当实例化一个对象的时候,就会为这个虚函数创建一个虚表,就是用来存储这个类中的虚函数地址

一.对于不进行继承的类中的虚函数与虚表

/*********************************************************************** * Copyright (c)2015,WK Studios * * Filename: A.h * * Compiler: GCC vc 6.0* * Author:WK* * Time: 2015 29 6 * **********************************************************************/ #include <iostream>using namespace std;class A{public:A(int x=0):m_data(x){ cout<<"——Create A::—–\n";}virtual void show(){cout<<"—show::Data: is: "<<m_data<<endl;}virtual void print(){cout<<"—print::Data: is: "<<m_data<<endl;}virtual ~A(){cout<<"——Free A::—–\n";}private:int m_data;};class B{public:B(int i=0):data(i){ cout<<"——Create B::—–\n";}virtual void show1(){cout<<"—show1::Data: is "<<data<<endl;}virtual void print1(){cout<<"—print1::Data: is: "<<data<<endl;}virtual ~B(){ cout<<"——Free B::—–\n";}private:int data;};typedef void (*P)();void main(){A a;cout<<"\n";cout<<"—–使用对象调用虚函数—-\n";a.print();a.show();cout<<endl;cout<<hex<<*(int *)(&a)<<endl;cout<<*(int*)(*(int*)(&a))<<endl;cout<<*(int*)((*(int*)(&a)+0))<<endl;cout<<"\n";cout<<"—–使用地址调用虚函数—-\n";int *q=(int*)(*(int *)(&a)); cout<<*q<<""<<*(q+1)<<endl;((void (*)())(*q))();((void (*)())(*(q+1)))();((void (*)())(q[0]))();cout<<"\n";P p,n;p=(P)(*(((int*)(*(int*)(&a)))+0));p();p=(P)(*(((int*)(*(int*)(&a)))+1));p();cout<<"\n";B b;cout<<"\n";b.print1();b.show1();cout<<"\n";}

所以现在当使用多态时候将 base*p; p= &Derived 实现多态的时候是把子类的对象的首部地址赋给这个指针,这个指针只能读取前4个字节所以就是虚表的首地址,之后根据函数名在虚表中调用虚函数,因为继承之后基类的与子类的三同函数,而且是虚函数被子类的函数覆盖,所以此时调用的只能是子类的函数,因此实现了多态!

三同是返回值 参数 函数名 全相同,想区分覆盖和隐藏请看这篇文章

二.对于单继承类的虚函数和虚表

/*********************************************************************** * Copyright (c)2015,WK Studios * * Filename: A.h * * Compiler: GCC vc 6.0* * Author:WK* * Time: 2015 29 6 * **********************************************************************/ #include <iostream>using namespace std;class A{public:A(int x=0):m_data(x){ cout<<"——Create A::—–\n";}virtual void show(){cout<<"—A::–show::Data: is: "<<m_data<<endl;}virtual void print(){cout<<"—A::–print::Data: is: "<<m_data<<endl;}virtual ~A(){cout<<"——Free A::—–\n";}private:int m_data;};class B:public A{public:B(int i=0,int j=0):data(i),A(j){ cout<<"——Create B::—–\n";} void show1(){cout<<"—B::–show1::Data: is "<<data<<endl;}void print(){cout<<"—B::–print::Data: is: "<<data<<endl;}virtual ~B(){ cout<<"——Free B::—–\n";}private:int data;};void main(){B a;}

这种覆盖只会出现在子类继承了父类的并且存在三同函数而且三同函数必须在基类中是虚函数,此时子类中继承父类的三同函数会在子类的虚表里被子类的函数覆盖,注意不是大家同用一个虚表对于任意一个实例化的类对象只要类中存在虚函数就会出现一个虚表,只是我们如果不再继承上使用覆盖来使用虚表就会使虚表失去原本用来实现动态连编的初衷,也就是多态的实现

可以自己测一下在基类被继承后基类的那个虚函数还在呢

上边的mian函数中加上一句 A b ;

明天又会是新的一天,而我依然年轻。

C++之探索多态的本质(虚函数与虚表)2

相关文章:

你感兴趣的文章:

标签云: