zoukankan      html  css  js  c++  java
  • C++里面多继承带来的指针漂移问题

    C++里面多继承带来的指针漂移问题





    C++里面多继承带来的指针漂移问题
    转载请注明出处:
    http://blog.csdn.net/phoenixsh
    最近我们在工作中碰到一个奇怪的问题,最后确定是多继承引起的指针漂移,跟C++对象模型有关。示意如下:
    class
     A 
    ...
    {...}
    ;
    class
     B
    ...
    {...}
    ;
    class
     AB : public B, public
     A 
    ...
    {...}
    ...
    AB 
    *
    pab 
    =
     
    new
     AB();
    A
    *
     pa 
    =
     (A
    *
    )pab;
    B
    *
     pb 
    =
     (B
    *
    )pab;
    这时候你发现pa和pb的值是不一样的!它们中有一个跟pab是相等的,而另外一个产生了偏移。如果把AB的声明中A和B的顺序调换一下,则产生偏移的指针也会变为另外一个。
    为了确定这是编译器做了转换的缘故,利用void指针愚弄编译器:
    void
     
    *
    pv 
    =
     (
    void
    *
    )pab;
    pa 
    =
     (A
    *
    )pv;
    这时候pa的值倒是跟pab相等了,然而指向了错误的地方。从pab到pa的转换,依赖于路径的选择,让人不是很放心。还不知道把指针放入容器中再取出来,会不会出错。当然,上面使用了强制类型转换,在良好的程序中应该避免。如果只有隐式转换,可以得到正确的结果:
    std::vector
    <
    A
    *>
     v;
    //
    implicit type conversion
    v.insert(v.begin(), pab);
    void
     
    *
    pv 
    =
     v[
    0
    ];
    pa 
    =
     (A
    *
    )pv;
    以下程序使用Cygwin/g++b编译通过:
    #include 
    <
    stdio.h
    >
    #include 
    <
    vector
    >
    class
     A 
    ...
    {
    public
    :
     
    int
     a;
    }
    ;
    class
     B 
    ...
    {
    public
    :
     
    int
     b;
    }
    ;
    class
     AB : 
    public
     B, 
    public
     A 
    ...
    {
    public
    :
     
    int
     ab;
    }
    ;
    int
     main(
    int
     argc, 
    char
     
    **
    argv)
    ...
    {
     AB 
    *
    pab 
    =
     
    new
     AB();
     pab
    ->
    ab 
    =
     
    1
    ;
     pab
    ->

    =
     
    2
    ;
     pab
    ->

    =
     
    3
    ;
     A
    *
     pa 
    =
     (A
    *
    )pab;
     B
    *
     pb 
    =
     (B
    *
    )pab;
     printf( 
    "
    AB: %p
    "
     
      
    "
     A: %p
    "
     
      
    "
     B: %p
    "
    ,
      pab, pa, pb);
     std::vector
    <
    A
    *>
     v;
     
    //
    implicit type conversion
     v.insert(v.begin(), pab);
     
    void
     
    *
    pv 
    =
     v[
    0
    ];
     pa 
    =
     (A
    *
    )pv;
     printf(
    "
    pv is %p pa is %p pab %s pv
    "
    , pv, pa, (pab 
    ==
     pv) 
    ?
     
    "
    ==
    "
     : 
    "
    !=
    "
    );
     printf(
    "
    A.a is %d
    "
    , pa
    ->
    a);
     
    //
    forced type conversion
     pv 
    =
     (
    void
    *
    )pab;
     pa 
    =
     (A
    *
    )pv;
     printf(
    "
    Now A.a is %d
    "
    , pa
    ->
    a);
    }

    这个很容易理解的
    class AB:public A,public B{/**/}
    类AB对象在内存中的排列是
    [A]
    [B]
    [AB独有]
    当把AB类对象指针转化为B对象指针时
    指针应该指向[B]区的开始位置而不是[A]区的开始位置

  • 相关阅读:
    Java 基础 泛型
    Hibernate 注解
    Head Fisrt Android Development读书笔记(7)Database Persistent
    ruby中的Enumerable的使用
    [置顶] 从small到safe,形容词的学问
    Silverlight中DomainDataSource的一种Debug方法
    [置顶] 从高中一次半夜不冲厕所的经历谈程序
    [置顶] 视频网站:一炷香后即将为您播放精彩内容
    Android. Handling some SQLite issues
    查找ruby方法(以rails为例)
  • 原文地址:https://www.cnblogs.com/liangouyang/p/1288769.html
Copyright © 2011-2022 走看看