注意C++中对象指针,慎用void*

原创 2007年10月07日 19:57:00

        由于不同C++编译器对C++对象模型的结构可能是不一样的。比如说,VC++系列是将虚函数表指针放在对象首地址,而GCC系列的编译器则是将虚函数表指针放在对象地址尾部。

        那么下面我将详细讲讲GCC编译器下的对象模型(含虚函数表指针)。

        先看下面这个例子:

 

#include <iostream>
using namespace std;


class A
...{
private:

    
int a;
    
public:

    A(
void) : a(0)
    
...{
        
    }


    
virtual void Hello(void)
    
...{
        cout 
<< "Hello, world!" << endl;
    }

}
;

class B : public A
...{
private:

    
int b;
    
public:

    B(
void) : b(1)
    
...{
        
    }


    
virtual void Hello(void)
    
...{
        cout 
<< "B!" << endl;
    }

}
;

         上面的示例中,A对象的地址中存放两个4字节的数据,一个是变量a,另一个是虚函数表指针。变量a放在低地址;虚函数表指针放在高地址,那么方便起见,我这样表示——A  objA = { a,  vptr  }。而B的对象首先是存放类A域的所有成员,然后是B自己的数据成员——B  objB = { a, vptr, b }。

        那么这样的安排就有助于编译器处理这样的情况了——

 

B b;
*= &b;
b
->Hello();

 

        那么如果是多继承或是虚继承会怎样呢?

        碰到这种情况,GCC或其兼容C++编译器会同时判断左操作数的类型以及有操作数的类型。根据左操作数的类型来判断左操作数的指针指向有操作数对象的哪个偏移地址。如果是其他类型的指针(如void*),则指向对象的首地址。

        下面请看一下详细的测试代码:

 

#include <iostream>
using namespace std;


class A
...{
private:

    
int a;
    
public:

    A(
void) : a(0)
    
...{
        
    }


    
virtual void Hello(void)
    
...{
        cout 
<< "Hello, world!" << endl;
    }

}
;


class AA
...{
private:

    
int aa;
    
public:

    AA(
void) : aa(100)
    
...{
        
    }

    
    
virtual void Hi(void)
    
...{
        cout 
<< "Hi, therte!" << endl;
    }

}
;


class B : public A
...{
private:

    
int b;
    
public:

    B(
void) : b(1)
    
...{
        
    }


    
virtual void Hello(void)
    
...{
        cout 
<< "B!" << endl;
    }

}
;


class C : virtual public A
...{
private:

    
int c, d;
    
public :

    C(
void) : c(2), d(3)
    
...{
        
    }

    
    
void Hello(void)
    
...{
        cout 
<< "C!" << endl;
    }

}
;


class E : public A, public AA
...{
private:

    
int e;
    
public:

    E(
void) : e(8)
    
...{
        
    }

    
    
void Hello(void)
    
...{
        cout 
<< "E!" << endl;
    }

    
    
void Hi(void)
    
...{
        cout 
<< "Hi!" << endl;
    }

}
;


extern "C" void test(void);


int main(void)
...{
    A a;
    B b;
    C c;
    E e;
    
    unsigned 
long s[10];
    
    
int i=0;
    
    
for(; i<sizeof(a) >> 2; i++)
        s[i] 
= ((unsigned long*)&a)[i];
        
    a.Hello();
    
    
for(i=0; i<sizeof(b) >> 2; i++)
        s[i] 
= ((unsigned long*)&b)[i];
        
    A 
*= &b;
    
    p
->Hello();
    
    
for(i=0; i<sizeof(c) >> 2; i++)
        s[i] 
= ((unsigned long*)&c)[i];
        
    p 
= &c;
    
    
void* q = (C*)&c;
    
    p
->Hello();
    
    
for(i=0; i<sizeof(e) >> 2; i++)
        s[i] 
= ((unsigned long*)&e)[i];
        
    AA 
*pp = &e;
    p 
= &e;
    q 
= &e;
    
    
return 0;
}

 

        在main函数中,上面的p和q两个指针的值是不同的,尽管它们指向同一个对象。p指向了对象c的A类域的偏移处;而q则是指向了p 的首地址。那么下面的pp和p及q也是不同,这里的p和q都是指向首地址,因为类A域在对象e的起始处,而pp则是指向了e的AA类域的偏移处。

        大家可以利用以上代码进行调试,有个感性认识。

        所以在C++中,甚用void*指针指向一个对象,否则当再次进行类型转换时,调用相关函数可能会发生意想不到的情况。那么这个时候还是利用模板,通过范型来解决类型问题,这样做更安全,而且更优美。

C++语言基础

-
  • 1970年01月01日 08:00

C++中void和void*指针的含义

转载:http://blog.chinaunix.net/uid-22197900-id-359211.html 转载:http://www.jb51.net/article/36570.htm   ...
  • Lee_Shuai
  • Lee_Shuai
  • 2016-11-17 00:12:45
  • 9859

C++ void*指针、多重指针void**和指针大小

一、定义:                用void*  定义一个void类型的指针,它不指向任何类型的数据,意思是,void*指针“指向空类型”或“不指向确定的类型”,而不要理解为void*指针能指...
  • Gordennizaicunzai
  • Gordennizaicunzai
  • 2017-09-16 23:31:10
  • 823

C++ void*用法记录

欢迎使用Markdown编辑器写博客本Markdown编辑器使用StackEdit修改而来,用它写博客,将会带来全新的体验哦: Markdown和扩展Markdown简洁的语法 代码块高亮 图片链接和...
  • xjsbkx
  • xjsbkx
  • 2017-12-18 14:54:54
  • 1086

万恶的void*指针类型转换

大家都知道:用一个基类的指针指向一个派生类的对象是合理的,然而很多人却忽略了这样做的大前提:必须使用规范的指针转换过程。 最近要添加一个功能,上层代码为此新增了一个虚函数接口。我一看,此虚函数所在的...
  • qq_21895115
  • qq_21895115
  • 2015-05-11 07:05:10
  • 2885

浅谈void指针的类型转换问题

指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。 要搞清一个指针需要搞清指针的四方面的内容:指针的类型、指针所指向的 类型、指针的值或者叫指针所指向的内存区、指针本身所占据的内存区。...
  • u012771236
  • u012771236
  • 2014-04-10 18:53:07
  • 4367

指向对象成员变量的指针

指向对象成员变量的指针
  • yanglingwell
  • yanglingwell
  • 2016-04-16 20:46:01
  • 18371

void指针详解

void指针的理解和使用都是比较复杂的,尤其与其他形式定义结合时,就显得更为复杂了。下面就综合网上一些资料,介绍一下void的用法。 1.void指针是一种特别的指针    void *vp ...
  • zycxnanwang
  • zycxnanwang
  • 2016-10-20 21:13:13
  • 2370

C/C++中的void和void*

C/C++中的void和void* C/C++中的void和void* 一、void void关键字表示“空类型”的概念。但是,这里的“空类型”不表示“任意类型”,而是表示不...
  • a48351217a
  • a48351217a
  • 2014-08-02 11:40:27
  • 370

C/C++中的函数中的void和void* 理解

C/C++中的void和void* 一、void void关键字表示“空类型”的概念。但是,这里的“空类型”不表示“任意类型”,而是表示不存在的意思,也就是说C/C++不允许你写语句voi...
  • qq_18343569
  • qq_18343569
  • 2015-07-31 20:22:04
  • 4274
收藏助手
不良信息举报
您举报文章:注意C++中对象指针,慎用void*
举报原因:
原因补充:

(最多只允许输入30个字)