Function overloading vs function overriding in c++
Ref
- https://www.geeksforgeeks.org/function-overloading-vs-function-overriding-in-cpp/
Example Cpp code
// CPP program to illustrate
// Function Overriding
#include<iostream>
using namespace std;
class BaseClass
{
public:
virtual void Display()
{
cout << "\nThis is Display() method"
" of BaseClass";
}
void Show()
{
cout << "\nThis is Show() method "
"of BaseClass";
}
};
class DerivedClass : public BaseClass
{
public:
// Overriding method - new working of
// base class's display method
void Display()
{
cout << "\nThis is Display() method"
" of DerivedClass";
}
};
// Driver code
int main()
{
DerivedClass dr;
BaseClass &bs = dr;
bs.Display();
dr.Show();
}
Class methods are just like others functions, that is they are just some code located somewhere in .text
(.code) section. Except that a class method will receive as its first argument the famous this
pointer (passed via rdi
register in this case). Also, you can see name mangling in actions here (ex: _ZN9BaseClass4ShowEv, _ZN12DerivedClass7DisplayEv
)
.text:0000000000000A6C ; =============== S U B R O U T I N E =======================================
.text:0000000000000A6C
.text:0000000000000A6C ; Attributes: static bp-based frame
.text:0000000000000A6C
.text:0000000000000A6C ; void __cdecl BaseClass::Show(BaseClass *const this)
.text:0000000000000A6C public _ZN9BaseClass4ShowEv ; weak
.text:0000000000000A6C _ZN9BaseClass4ShowEv proc near ; CODE XREF: main+44↑p
.text:0000000000000A6C
.text:0000000000000A6C this = qword ptr -8
.text:0000000000000A6C
.text:0000000000000A6C ; __unwind {
.text:0000000000000A6C push rbp
.text:0000000000000A6D mov rbp, rsp
.text:0000000000000A70 sub rsp, 10h
.text:0000000000000A74 mov [rbp+this], rdi ; rdi = the *this* pointer
.text:0000000000000A78 lea rsi, aThisIsShowMeth ; "\nThis is Show() method of BaseClass"
.text:0000000000000A7F lea rdi, _ZSt4cout@@GLIBCXX_3_4
.text:0000000000000A86 call __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
.text:0000000000000A8B nop
.text:0000000000000A8C leave
.text:0000000000000A8D retn
.text:0000000000000A8D ; } // starts at A6C
.text:0000000000000A8D _ZN9BaseClass4ShowEv endp
.text:0000000000000A8D
.text:0000000000000A8E
.text:0000000000000A8E ; =============== S U B R O U T I N E =======================================
.text:0000000000000A8E
.text:0000000000000A8E ; Attributes: static bp-based frame
.text:0000000000000A8E
.text:0000000000000A8E ; void __cdecl DerivedClass::Display(DerivedClass *const this)
.text:0000000000000A8E public _ZN12DerivedClass7DisplayEv ; weak
.text:0000000000000A8E _ZN12DerivedClass7DisplayEv proc near ; DATA XREF: .data.rel.ro:off_201D68↓o
.text:0000000000000A8E
.text:0000000000000A8E this = qword ptr -8
.text:0000000000000A8E
.text:0000000000000A8E ; __unwind {
.text:0000000000000A8E push rbp
.text:0000000000000A8F mov rbp, rsp
.text:0000000000000A92 sub rsp, 10h
.text:0000000000000A96 mov [rbp+this], rdi
.text:0000000000000A9A lea rsi, aThisIsDisplayM ; "\nThis is Display() method of DerivedCl"...
.text:0000000000000AA1 lea rdi, _ZSt4cout@@GLIBCXX_3_4
.text:0000000000000AA8 call __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
.text:0000000000000AAD nop
.text:0000000000000AAE leave
.text:0000000000000AAF retn
.text:0000000000000AAF ; } // starts at A8E
.text:0000000000000AAF _ZN12DerivedClass7DisplayEv endp
.text:0000000000000AAF
Vtable
of a class is just array of function pointers to its virtual functions which located somewhere in read-only data section (.data.rel.ro
)
.data.rel.ro:0000000000201D58 ; `vtable for'DerivedClass
.data.rel.ro:0000000000201D58 _ZTV12DerivedClass dq 0 ; offset to this
.data.rel.ro:0000000000201D60 dq offset _ZTI12DerivedClass ; `typeinfo for'DerivedClass
.data.rel.ro:0000000000201D68 off_201D68 dq offset _ZN12DerivedClass7DisplayEv
.data.rel.ro:0000000000201D68 ; DATA XREF: main+17↑o
.data.rel.ro:0000000000201D68 ; DerivedClass::Display(void)
This is how compiler setup and call correct function in case of polymorphism
.text:00000000000009AA ; =============== S U B R O U T I N E =======================================
.text:00000000000009AA
.text:00000000000009AA ; Attributes: bp-based frame
.text:00000000000009AA
.text:00000000000009AA ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00000000000009AA public main
.text:00000000000009AA main proc near ; DATA XREF: _start+1D↑o
.text:00000000000009AA
.text:00000000000009AA dr = DerivedClass ptr -18h
.text:00000000000009AA bs = qword ptr -10h
.text:00000000000009AA var_8 = qword ptr -8
.text:00000000000009AA
.text:00000000000009AA ; __unwind {
.text:00000000000009AA push rbp
.text:00000000000009AB mov rbp, rsp
.text:00000000000009AE sub rsp, 20h
.text:00000000000009B2 mov rax, fs:28h
.text:00000000000009BB mov [rbp+var_8], rax
.text:00000000000009BF xor eax, eax
.text:00000000000009C1 lea rax, off_201D68 ; vtable for *DerivedClass*
.text:00000000000009C8 mov [rbp+dr.baseclass_0._vptr_BaseClass], rax ; vptr of *ds* = off_201D68
.text:00000000000009CC lea rax, [rbp+dr] ; rax = addr of *dr*
.text:00000000000009D0 mov [rbp+bs], rax ; vptr of *bs* = vptr of *ds*
.text:00000000000009D4 mov rax, [rbp+bs] ; rax = vptr of *bs*
.text:00000000000009D8 mov rax, [rax] ; rax = addr of vtable of *bs*
.text:00000000000009DB mov rax, [rax] ; rax = first func in vtable of *bs*
.text:00000000000009DE mov rdx, [rbp+bs] ; rdx = addr of *bs/dr*
.text:00000000000009E2 mov rdi, rdx ; rdi = addr of *bs/dr*
.text:00000000000009E5 call rax ; call *Display* function with first arg in *rdi* (this pointer)
.text:00000000000009E7 lea rax, [rbp+dr]
.text:00000000000009EB mov rdi, rax ; this
.text:00000000000009EE call _ZN9BaseClass4ShowEv ; BaseClass::Show(void)
.text:00000000000009F3 mov eax, 0
.text:00000000000009F8 mov rcx, [rbp+var_8]
.text:00000000000009FC xor rcx, fs:28h
.text:0000000000000A05 jz short locret_A0C
.text:0000000000000A07 call ___stack_chk_fail
.text:0000000000000A0C ; ---------------------------------------------------------------------------
.text:0000000000000A0C
.text:0000000000000A0C locret_A0C: ; CODE XREF: main+5B↑j
.text:0000000000000A0C leave
.text:0000000000000A0D retn
.text:0000000000000A0D ; } // starts at 9AA
.text:0000000000000A0D main endp
Pseudo code of the main
function above
int __cdecl main(int argc, const char **argv, const char **envp)
{
DerivedClass dr; // [rsp+8h] [rbp-18h]
BaseClass *bs; // [rsp+10h] [rbp-10h]
unsigned __int64 v6; // [rsp+18h] [rbp-8h]
v6 = __readfsqword(0x28u);
dr._vptr_BaseClass = (int (**)(...))&off_201D68;
bs = (BaseClass *)&dr;
DerivedClass::Display(&dr);
BaseClass::Show(&dr.0);
return 0;
}