虽然我不确定这是否是确切的答案,但这是我的理解。 (另外,我的 CPP 术语不好 - 如果可能,请忽略它)
对于 C++,当声明任何类时(即尚未创建即时),函数将放置在正在创建的二进制文件的 .text 部分中。创建瞬间时,函数或方法不重复。也就是说,当编译器解析 CPP 文件时,它会将 ptr->print() 的函数调用替换为 .text 部分中定义的适当地址。
因此,编译器所要做的就是根据函数print 的ptr 的类型 替换适当的地址。 (这也意味着一些检查相关的公共/私有/继承等)
我为您的代码(名为test12.cpp)做了以下操作:
编辑:在下面添加一些 cmets 到 ASM(我真的_不_擅长 ASM,我几乎看不懂它 - 足以理解一些基本的东西) - 最好是阅读 this Wikibook link,我也是已经完成了:D
如果有人在 ASW 中发现错误,请发表评论 - 我很乐意修复它们并了解更多信息。
$ g++ test.cpp -S
$ cat test.s
...
// Following snippet is part of main function call
movl $0, -8(%ebp) //this is for creating the NULL pointer ABC* ptr=NULL
//It sets first 8 bytes on stack to '0'
movl -8(%ebp), %eax //Load the ptr pointer into eax register
movl %eax, (%esp) //Push the ptr on stack for using in function being called below
//This is being done assuming that these elements would be used
//in the print() function being called
call _ZN3ABC5printE //Call to print function after pushing arguments (which are none) and
//accesss pointer (ptr) on stack.
...
vWhereZN3ABC5printEv代表class ABC中定义的函数的全局定义:
...
.LC0: //This declares a label named .LC0
.string "hello" // String "hello" which was passed in print()
.section .text._ZN3ABC5printEv,"axG",@progbits,_ZN3ABC5printEv,comdat
.align 2
.weak _ZN3ABC5printEv //Not sure, but something to do with name mangling
.type _ZN3ABC5printEv, @function
_ZN3ABC5printEv: //Label for function print() with mangled name
//following is the function definition for print() function
.LFB1401: //One more lavbel
pushl %ebp //Save the 'last' known working frame pointer
.LCFI9:
movl %esp, %ebp //Set frame (base pointer ebp) to current stack top (esp)
.LCFI10:
subl $8, %esp //Allocating 8 bytes space on stack
.LCFI11:
movl $.LC0, 4(%esp) //Pushing the string represented by label .LC0 in
//in first 4 bytes of stack
movl $_ZSt4cout, (%esp) //Something to do with "cout<<" statement
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)
movl %eax, (%esp)
call _ZNSolsEPFRSoS_E //Probably call to some run time library for 'cout'
leave //end of print() function
ret //returning control back to main()
...
因此,即使((ABC *)0)->print(); 也能正常工作。