The function is stored inside .text
segment.
A compiled program’s memory is divided into five segments: text,
data, bss, heap, and stack. Each segment represents a special portion
of memory that is set aside for a certain purpose. The text segment is
also sometimes called the code segment. This is where the assembled
machine language instructions of the program are located.
The memory layout of the object itself is:
class ABC_ {
public:
int a; // 0x4 (4)
int b; // 0x8 (8)
int c; // 0xC (12)
int foobar(int a) { // you can print address using &foobar
return a;
}
};
When your class contains virtual functions they're stored in the same way but memory layout of your class changes... it will have one invisible 4 byte(on 32 bit) pointer to the virtual function table or virtual method table/ VMT (this table simply holds addresses of the functions to allow polymorphism, such table is created for each class separately, when it inherits another table is stored in memory) so in that case the size would be 16. It also depends on alignment setting of the compiler...
If you want to get pointer to a vtable you can do it this way:
void **get_vtable(void *obj) {
return *(void ***)obj;
}
Vtable is usually stored at the beginning in every compiler I know.
You can notice the difference when function is virtual and when not by looking at the way it's called. Normal functions are directly called/jmped but virtual ones, they're called by function pointer stored in their table.
(some x86 asm out of my mind, could be wrong)
mov edx, [ecx] // ecx = this pointer
add edx, 12h // let's say 0x12 is the offset divided by 4 is 4 = index in vtable
call edx // you know it's virtual function
or simply
mov edx, [ecx+12h]
call edx
The best way to learn how things are stored in memory is to use some disassembler and/or debugger. I recommend IDA Pro and x64dbg.