类继承时的虚函数(表)问题

 

当类出现继承时,可以分为两种情况:
      1. 类中没有虚函数
      2. 类中存在虚函数(当类中存在虚函数时,对象中会引入一个虚函数表(为一个指针),占四个字节)
           此时,问题便涉及到类中虚函数的继承与覆盖问题:
  •         a. 类对象中,各个变量及成员的访问法则:   
class Base
{
public:
	int a;
	char d;
	virtual void f(void) { cout << "Base::f" <<endl; }
	virtual void g(void) { cout << "Base::g" << endl; }
	virtual void h(void) { cout << "Base::h" << endl; }
};
 typedef void (*Func)(void);
 Base b;
 b.a = 1;
 b.d = 'd';
 Func pfun = NULL;
 cout << "虚函数表的地址: " << &b <<" " << endl;
 cout << "虚函数表--第一个函数的地址: " << (int*)*(int*)(&b) + 0 << endl;
 cout << "其他元素的地址如下:" << endl;
 cout << "a: " << (int*)(&b) + 1 <<" "<< *((int*)(&b) + 1) << endl;
 cout << "d: " << ((int*)(&b) + 2) <<" "<< *(char*)((int*)(&b) + 2) << endl;
 pfun = ((Func)*(int*)*(int*)(&b));
 pfun();

 

 

            通过上述代码验证,&b 操作取得了虚函数表的地址,对象中成员的地址以及虚函数的存放如下图所示:
        
             
           * 上图所述的虚函数的地址本质上为对应虚函数放置在虚函数表中的位置!故而在内存上只相差一个指针的size!
  •        b. 由 base1 派生 BaseDer 

 

 

 

class BaseDer :public Base{public:virtual void f(void) { cout << "BaserDer::f" << endl; }virtual void i(void) { cout << "BaseDer::i" << endl; }};
BaseDer bd; cout << "虚函数表的地址: " << &bd << endl; cout << "虚函数表--第一个函数的地址: " << (int*)*(int*)(&bd) << endl; cout << "虚函数表--第四个函数的地址: " << (int*)*(int*)(&bd + 3) << endl; pfun = (Func)*((int*)*(int*)(&bd)); pfun(); pfun = (Func)*((int*)*(int*)(&bd) + 3); pfun();

 

 

            此时,创建对象 BaseDer bd。那么,对于对象 bd 来说,其虚函数表发生了什么变化?
                               
            经过继承覆盖之后,子类的虚函数直接覆盖父类的虚函数,剩余的新添加的虚函数便续接在父类虚函数表之后。
  •       c. 子类 BaseDer2 继承于多各类 base1,base2
                此时,BaseDer2 中有两个虚函数表(按照继承的顺序排布,此处与验证的有些出入,原因待查找),BaseDer2 中新             增加的虚函数则续接在继承的 第一个父类 之后。
 
 
class BaseDer2 :public Base, public Base2{public:virtual void f(void) { cout << "BaseDer2::f" << endl; }virtual void f2(void) { cout << "BaseDer2::f2" << endl; }
        virtual void add(void){ cout << "BaseDer2::add" << endl; }};BaseDer2 bd2;bd2.a = 2;BaseDer2 bd2;bd2.a = 2;cout << "继承后的虚函数表:" << &bd2 << " " << (int*)(&bd2) << endl;cout << "继承后的虚函数表中的地址:" << endl;pfun = (Func)*((int*)*(int*)(&bd2) + 0);pfun();pfun = (Func)*((int*)*(int*)(&bd2) + 1);pfun();pfun = (Func)*((int*)*(int*)(&bd2) + 2);pfun();pfun = (Func)*((int*)*(int*)(&bd2) + 3);pfun();cout << *((int*)(&bd2) + 1) << endl; 
 
pfun = (Func)*((int*)*((int*)(&bd2) + 1));pfun();

 

     

    理论上由两个 父类 继承而来,此处的 子类 应该有两个 顺序排布的虚函数表,但是对“第二个虚函数表”进行访问时,发现访问到的数据是 类中的成员变量,并未访问到第二个虚函数表!!!此处没有弄清楚原因所在!

使用父类指针指向子类时,指针指向的是其对应虚函数表的地址!!!

由多个类派生出来的子类,子类中成员于内存中的排布顺序:

Father : 虚函数表f,成员变量 a;

Mother: 虚函数表m,成员变量b;

Son:     虚函数表f;

            成员变量a;

            虚函数表m;

            成员变量b;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值