【问题标题】:How does member function knows that it is called for specific object?成员函数如何知道它是为特定对象调用的?
【发布时间】:2011-11-20 14:33:35
【问题描述】:

有这样的C++代码:

#include <iostream>

class MojaKlasa{
public:
  int z;
  void fun(){ std::cout << this;};
};

int main()
{
  MojaKlasa a;
  a.z = 2;
  a.fun();
  return 0;
}

以及对应的汇编代码:

    .file   "prog50.cpp"
    .local  _ZStL8__ioinit
    .comm   _ZStL8__ioinit,1,1
    .section    .text._ZN9MojaKlasa3funEv,"axG",@progbits,_ZN9MojaKlasa3funEv,comdat
    .align 2
    .weak   _ZN9MojaKlasa3funEv
    .type   _ZN9MojaKlasa3funEv, @function
_ZN9MojaKlasa3funEv:
.LFB957:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    subl    $24, %esp
    movl    8(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    $_ZSt4cout, (%esp)
    call    _ZNSolsEPKv
    leave
    ret
    .cfi_endproc
.LFE957:
    .size   _ZN9MojaKlasa3funEv, .-_ZN9MojaKlasa3funEv
    .text
.globl main
    .type   main, @function
main:
.LFB958:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $32, %esp
    movl    $2, 28(%esp)     # a.z = 2;
    leal    28(%esp), %eax
    movl    %eax, (%esp)
    call    _ZN9MojaKlasa3funEv   # a.fun();
    movl    $0, %eax
    leave
    ret
    .cfi_endproc
.LFE958:
    .size   main, .-main
    .type   _Z41__static_initialization_and_destruction_0ii, @function
_Z41__static_initialization_and_destruction_0ii:
.LFB960:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    subl    $24, %esp
    cmpl    $1, 8(%ebp)
    jne .L7
    cmpl    $65535, 12(%ebp)
    jne .L7
    movl    $_ZStL8__ioinit, (%esp)
    call    _ZNSt8ios_base4InitC1Ev
    movl    $_ZNSt8ios_base4InitD1Ev, %eax
    movl    $__dso_handle, 8(%esp)
    movl    $_ZStL8__ioinit, 4(%esp)
    movl    %eax, (%esp)
    call    __cxa_atexit
.L7:
    leave
    ret
    .cfi_endproc
.LFE960:
    .size   _Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii
    .type   _GLOBAL__I_main, @function
_GLOBAL__I_main:
.LFB961:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    subl    $24, %esp
    movl    $65535, 4(%esp)
    movl    $1, (%esp)
    call    _Z41__static_initialization_and_destruction_0ii
    leave
    ret
    .cfi_endproc
.LFE961:
    .size   _GLOBAL__I_main, .-_GLOBAL__I_main
    .section    .ctors,"aw",@progbits
    .align 4
    .long   _GLOBAL__I_main
    .weakref    _ZL20__gthrw_pthread_oncePiPFvvE,pthread_once
    .weakref    _ZL27__gthrw_pthread_getspecificj,pthread_getspecific
    .weakref    _ZL27__gthrw_pthread_setspecificjPKv,pthread_setspecific
    .weakref    _ZL22__gthrw_pthread_createPmPK14pthread_attr_tPFPvS3_ES3_,pthread_create
    .weakref    _ZL20__gthrw_pthread_joinmPPv,pthread_join
    .weakref    _ZL21__gthrw_pthread_equalmm,pthread_equal
    .weakref    _ZL20__gthrw_pthread_selfv,pthread_self
    .weakref    _ZL22__gthrw_pthread_detachm,pthread_detach
    .weakref    _ZL22__gthrw_pthread_cancelm,pthread_cancel
    .weakref    _ZL19__gthrw_sched_yieldv,sched_yield
    .weakref    _ZL26__gthrw_pthread_mutex_lockP15pthread_mutex_t,pthread_mutex_lock
    .weakref    _ZL29__gthrw_pthread_mutex_trylockP15pthread_mutex_t,pthread_mutex_trylock
    .weakref    _ZL31__gthrw_pthread_mutex_timedlockP15pthread_mutex_tPK8timespec,pthread_mutex_timedlock
    .weakref    _ZL28__gthrw_pthread_mutex_unlockP15pthread_mutex_t,pthread_mutex_unlock
    .weakref    _ZL26__gthrw_pthread_mutex_initP15pthread_mutex_tPK19pthread_mutexattr_t,pthread_mutex_init
    .weakref    _ZL29__gthrw_pthread_mutex_destroyP15pthread_mutex_t,pthread_mutex_destroy
    .weakref    _ZL30__gthrw_pthread_cond_broadcastP14pthread_cond_t,pthread_cond_broadcast
    .weakref    _ZL27__gthrw_pthread_cond_signalP14pthread_cond_t,pthread_cond_signal
    .weakref    _ZL25__gthrw_pthread_cond_waitP14pthread_cond_tP15pthread_mutex_t,pthread_cond_wait
    .weakref    _ZL30__gthrw_pthread_cond_timedwaitP14pthread_cond_tP15pthread_mutex_tPK8timespec,pthread_cond_timedwait
    .weakref    _ZL28__gthrw_pthread_cond_destroyP14pthread_cond_t,pthread_cond_destroy
    .weakref    _ZL26__gthrw_pthread_key_createPjPFvPvE,pthread_key_create
    .weakref    _ZL26__gthrw_pthread_key_deletej,pthread_key_delete
    .weakref    _ZL30__gthrw_pthread_mutexattr_initP19pthread_mutexattr_t,pthread_mutexattr_init
    .weakref    _ZL33__gthrw_pthread_mutexattr_settypeP19pthread_mutexattr_ti,pthread_mutexattr_settype
    .weakref    _ZL33__gthrw_pthread_mutexattr_destroyP19pthread_mutexattr_t,pthread_mutexattr_destroy
    .ident  "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
    .section    .note.GNU-stack,"",@progbits
  1. 似乎 MojaKlasa 类的函数 fun() 被翻译为普通的常规函数​​。函数如何知道它是为特定对象调用的,例如 a.fun() -> 为对象 a 调用 fun()

  2. 第二个问题是,MojaKlasa 类的默认构造函数和析构函数在哪里?据说C++会自动为类创建构造函数和析构函数,但汇编代码中似乎没有包含其中一个。

【问题讨论】:

标签: c++ class


【解决方案1】:

函数如何知道它是为特定对象调用的,例如a.fun() -&gt; call fun() for object a

指向对象this 的指针作为第一个隐藏参数隐式传递给成员函数。

class MojaKlasa 的默认构造函数和析构函数在哪里?

C++ 原则是:你只为你使用的东西付费。
除非您的代码明确需要默认的无参数构造函数,否则编译器不会生成它。

【讨论】:

    【解决方案2】:

    根本不用看汇编代码,你应该知道成员函数传递了一个隐藏参数。这称为this 指针。因此,调用有自己的 this 指针,每个函数都是专门为该对象调用的。

    关于您的第二个问题,您可以放心,默认构造函数和析构函数已生成,但如果没有 gcc 编译器内部的专业知识,很难找出调用它的位置或方式。

    我在 Visual Studio 2010 中尝试过,但在反汇编中也找不到此信息。

    【讨论】:

      【解决方案3】:

      简而言之,成员函数有一个隐藏参数:

      void Class::func(int i); // Becomes...
      void func(Class const* this, int i);
      

      当您调用函数obj.func(7) 时,它会“转换”为func(&amp;obj, 7)。差不多就是这样。

      在 C++ 中,这是一个隐藏/隐式参数,但有些语言要求这是一个显式参数。例如,在 Python 中,你必须这样写(Python 中的self 相当于 C++ 中的 this):

      class Class:
          def func(self, i):
              ...
      

      【讨论】:

        猜你喜欢
        • 2017-12-29
        • 1970-01-01
        • 2011-05-27
        • 2021-05-19
        • 2013-09-16
        • 1970-01-01
        • 2012-01-02
        相关资源
        最近更新 更多