c++理解(四)

        本文主要探讨c++相关知识。

类大小:

        空类大小为1字节
        虚函数表(vptr)大小4个字节
        继承需要交基类大小,虚继承的派生类也有vptr
        静态成员在静态区域不占内存
        成员函数地址在代码段不占字节

继承本质是代码复用,class默认是private继承,struct默认是public继承
外部只能访问对象public成员,protected和private成员无法直接访问,派生类可继承private成员却无法直接访问,基类定义protected成员被派生类访问不被外部访问
派生类继承基类所有成员除构造和析构,派生类继承的成员初始化和析构由基类构造和析构完成
重载是同一作用域且函数名相同,参数列表不同,隐藏是派生类隐藏基类同名成员
静态绑定在编译时确定调用,调用效率高但灵活性低适用于非虚函数,函数重载,普通函数调用,动态绑定在运行时确定调用,调用效率低但灵活性高,适用于虚函数调用和多态
类定义虚函数在编译时产生vftable函数表(类中添加vptr指向vftable),vftable存储RTTI指针和虚函数地址,运行时将虚函数表加载到.rodata
类定义虚函数则类定义对象后运行时会存储vfptr虚函数指针指向相应虚函数表vftable,定义多个对象时vfpt指向同一虚函数表,类中虚函数个数不影响对象大小影响虚函数表大小
派生和基类方法、返回值、函数名、参数相同,基类为虚函数派生类方法自动为成虚函数,构造函数函数都是静态绑定,包括构造函数中的虚函数
析构函数不为虚函数(动态绑定),基类指针指向派生类时,析构函数静态绑定成基类析构函数,派生类开辟的内存由于不能调用派生类析构函数而泄漏内存
基类指针指向堆开辟的派生类对象,delete基类指针调用析构函数必须为动态绑定(基类为虚析构)
静态多态(编译):函数重载,模板(函数模板,类模板),动态多态(运行):基基类指针(引用)指向派生类对象通过该指针(引用)调用同名覆盖的虚函数

抽象类不能实例化对象可定义指针和引用变量,类对象通过该指针(引用)调用同名覆盖的虚函数
成员方法调用在运行阶段确定,默认参数和访问权限在编译阶段(字面判断调用)确定,静态绑定时运行时确定,动态绑定时运行时确定

基类和派生类的存储类型和顺序:

class C
{
        public:
                int a;
                int b;
                virtual void func1() = 0;
                void func2();
};

class C1 : public class C
{
        public:
                int c;
                virtual void func1() = 0;
                virtual void func3() = 0;
                void func4();
};

demo1: 

        静态绑定,动态绑定

结构图

代码示例:

CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 3.28)                            #最低版本要求
 
SET(CMAKE_CXX_COMPILER "g++-11")                                #设置g++编译器
 
PROJECT(CLASS)                                                  #设置工程名
 
MESSAGE(STATUS "CPP test")                                      #打印消息
 
ADD_EXECUTABLE(pro test.cpp)                                    #生成可执行文件

run.sh

#!/bin/bash
 
if [ -f ./Makefile ]
then
        make clean
fi
 
cmake .
 
make
 
echo "---------------------------------"
 
./pro

g++ test.cpp -o test -g

objdump -S test > test.dis

clean.sh

rm -rf CMakeCache.txt CMakeFiles Makefile cmake_install.cmake *.o pro test test.dis

test.cpp

#include <iostream>

class C
{
        public:
                void func()
                {
                        std::cout << "C::func()" << std::endl;
                }
};

class C1 : public C
{
        public:
                void func()
                {
                        std::cout << "C1::func()" << std::endl;
                }
};

class C2
{
        public:
                virtual void func()
                {
                        std::cout << "C2:func()" << std::endl;
                }
};

class C3 : public C2
{
        public:
                void func()
                {
                        std::cout << "C3::func()" << std::endl;
                }
};

class C4
{
        public:
                virtual void func()
                {
                        std::cout << "C4::func()" << std::endl; 
                }

                C4()
                {
                        std::cout << "C4()" << std::endl;
                        func();
                }
};

int main()
{
        C c;
        C1 c1;
        C2 c2;
        C3 c3;

        //静态绑定(编译时确定)
        c.func();
        c1.func();
        c2.func();
        c3.func();

        C *pc = &c1;
        pc->func();             //静态绑定(编译时确定)

        C2 *pc2 = &c3;
        pc2->func();            //动态绑定(运行时确定)


        pc = &c;                //静态绑定(编译时确定)
        pc->func();

        C1 *pc1 = &c1;          //静态绑定(编译时确定)
        pc1->func();

        pc2 = &c2;              //动态绑定(运行时确定)
        pc2->func();

        C3 *pc3 = &c3;
        pc3->func();            //动态绑定(运行时确定)

        C4 c4;                  //定义在构造函数中的虚函数为静态绑定(编译时确定)

        return 0;
}

结果示例:

结果图: 

test.dis 

 

 test.dis

test:     文件格式 elf64-x86-64


Disassembly of section .init:

0000000000001000 <_init>:
    1000:       f3 0f 1e fa             endbr64
    1004:       48 83 ec 08             sub    $0x8,%rsp
    1008:       48 8b 05 e1 2f 00 00    mov    0x2fe1(%rip),%rax        # 3ff0 <__gmon_start__@Base>
    100f:       48 85 c0                test   %rax,%rax
    1012:       74 02                   je     1016 <_init+0x16>
    1014:       ff d0                   call   *%rax
    1016:       48 83 c4 08             add    $0x8,%rsp
    101a:       c3                      ret

Disassembly of section .plt:

0000000000001020 <.plt>:
    1020:       ff 35 82 2f 00 00       push   0x2f82(%rip)        # 3fa8 <_GLOBAL_OFFSET_TABLE_+0x8>
    1026:       ff 25 84 2f 00 00       jmp    *0x2f84(%rip)        # 3fb0 <_GLOBAL_OFFSET_TABLE_+0x10>
    102c:       0f 1f 40 00             nopl   0x0(%rax)
    1030:       f3 0f 1e fa             endbr64
    1034:       68 00 00 00 00          push   $0x0
    1039:       e9 e2 ff ff ff          jmp    1020 <_init+0x20>
    103e:       66 90                   xchg   %ax,%ax
    1040:       f3 0f 1e fa             endbr64
    1044:       68 01 00 00 00          push   $0x1
    1049:       e9 d2 ff ff ff          jmp    1020 <_init+0x20>
    104e:       66 90                   xchg   %ax,%ax
    1050:       f3 0f 1e fa             endbr64
    1054:       68 02 00 00 00          push   $0x2
    1059:       e9 c2 ff ff ff          jmp    1020 <_init+0x20>
    105e:       66 90                   xchg   %ax,%ax

Disassembly of section .plt.got:

0000000000001060 <__cxa_finalize@plt>:
    1060:       f3 0f 1e fa             endbr64
    1064:       ff 25 66 2f 00 00       jmp    *0x2f66(%rip)        # 3fd0 <__cxa_finalize@GLIBC_2.2.5>
    106a:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

Disassembly of section .plt.sec:

0000000000001070 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>:
    1070:       f3 0f 1e fa             endbr64
    1074:       ff 25 3e 2f 00 00       jmp    *0x2f3e(%rip)        # 3fb8 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@GLIBCXX_3.4>
    107a:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

0000000000001080 <_ZNSolsEPFRSoS_E@plt>:
    1080:       f3 0f 1e fa             endbr64
    1084:       ff 25 36 2f 00 00       jmp    *0x2f36(%rip)        # 3fc0 <_ZNSolsEPFRSoS_E@GLIBCXX_3.4>
    108a:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

0000000000001090 <__stack_chk_fail@plt>:
    1090:       f3 0f 1e fa             endbr64
    1094:       ff 25 2e 2f 00 00       jmp    *0x2f2e(%rip)        # 3fc8 <__stack_chk_fail@GLIBC_2.4>
    109a:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

Disassembly of section .text:

00000000000010a0 <_start>:
    10a0:       f3 0f 1e fa             endbr64
    10a4:       31 ed                   xor    %ebp,%ebp
    10a6:       49 89 d1                mov    %rdx,%r9
    10a9:       5e                      pop    %rsi
    10aa:       48 89 e2                mov    %rsp,%rdx
    10ad:       48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
    10b1:       50                      push   %rax
    10b2:       54                      push   %rsp
    10b3:       45 31 c0                xor    %r8d,%r8d
    10b6:       31 c9                   xor    %ecx,%ecx
    10b8:       48 8d 3d ca 00 00 00    lea    0xca(%rip),%rdi        # 1189 <main>
    10bf:       ff 15 1b 2f 00 00       call   *0x2f1b(%rip)        # 3fe0 <__libc_start_main@GLIBC_2.34>
    10c5:       f4                      hlt
    10c6:       66 2e 0f 1f 84 00 00    cs nopw 0x0(%rax,%rax,1)
    10cd:       00 00 00 

00000000000010d0 <deregister_tm_clones>:
    10d0:       48 8d 3d 39 2f 00 00    lea    0x2f39(%rip),%rdi        # 4010 <__TMC_END__>
    10d7:       48 8d 05 32 2f 00 00    lea    0x2f32(%rip),%rax        # 4010 <__TMC_END__>
    10de:       48 39 f8                cmp    %rdi,%rax
    10e1:       74 15                   je     10f8 <deregister_tm_clones+0x28>
    10e3:       48 8b 05 fe 2e 00 00    mov    0x2efe(%rip),%rax        # 3fe8 <_ITM_deregisterTMCloneTable@Base>
    10ea:       48 85 c0                test   %rax,%rax
    10ed:       74 09                   je     10f8 <deregister_tm_clones+0x28>
    10ef:       ff e0                   jmp    *%rax
    10f1:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
    10f8:       c3                      ret
    10f9:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)

0000000000001100 <register_tm_clones>:
    1100:       48 8d 3d 09 2f 00 00    lea    0x2f09(%rip),%rdi        # 4010 <__TMC_END__>
    1107:       48 8d 35 02 2f 00 00    lea    0x2f02(%rip),%rsi        # 4010 <__TMC_END__>
    110e:       48 29 fe                sub    %rdi,%rsi
    1111:       48 89 f0                mov    %rsi,%rax
    1114:       48 c1 ee 3f             shr    $0x3f,%rsi
    1118:       48 c1 f8 03             sar    $0x3,%rax
    111c:       48 01 c6                add    %rax,%rsi
    111f:       48 d1 fe                sar    $1,%rsi
    1122:       74 14                   je     1138 <register_tm_clones+0x38>
    1124:       48 8b 05 cd 2e 00 00    mov    0x2ecd(%rip),%rax        # 3ff8 <_ITM_registerTMCloneTable@Base>
    112b:       48 85 c0                test   %rax,%rax
    112e:       74 08                   je     1138 <register_tm_clones+0x38>
    1130:       ff e0                   jmp    *%rax
    1132:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
    1138:       c3                      ret
    1139:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)

0000000000001140 <__do_global_dtors_aux>:
    1140:       f3 0f 1e fa             endbr64
    1144:       80 3d 05 30 00 00 00    cmpb   $0x0,0x3005(%rip)        # 4150 <completed.0>
    114b:       75 2b                   jne    1178 <__do_global_dtors_aux+0x38>
    114d:       55                      push   %rbp
    114e:       48 83 3d 7a 2e 00 00    cmpq   $0x0,0x2e7a(%rip)        # 3fd0 <__cxa_finalize@GLIBC_2.2.5>
    1155:       00 
    1156:       48 89 e5                mov    %rsp,%rbp
    1159:       74 0c                   je     1167 <__do_global_dtors_aux+0x27>
    115b:       48 8b 3d a6 2e 00 00    mov    0x2ea6(%rip),%rdi        # 4008 <__dso_handle>
    1162:       e8 f9 fe ff ff          call   1060 <__cxa_finalize@plt>
    1167:       e8 64 ff ff ff          call   10d0 <deregister_tm_clones>
    116c:       c6 05 dd 2f 00 00 01    movb   $0x1,0x2fdd(%rip)        # 4150 <completed.0>
    1173:       5d                      pop    %rbp
    1174:       c3                      ret
    1175:       0f 1f 00                nopl   (%rax)
    1178:       c3                      ret
    1179:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)

0000000000001180 <frame_dummy>:
    1180:       f3 0f 1e fa             endbr64
    1184:       e9 77 ff ff ff          jmp    1100 <register_tm_clones>

0000000000001189 <main>:
                        func();
                }
};

int main()
{
    1189:       f3 0f 1e fa             endbr64
    118d:       55                      push   %rbp
    118e:       48 89 e5                mov    %rsp,%rbp
    1191:       48 83 ec 50             sub    $0x50,%rsp
    1195:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
    119c:       00 00 
    119e:       48 89 45 f8             mov    %rax,-0x8(%rbp)
    11a2:       31 c0                   xor    %eax,%eax
        C c;
        C1 c1;
        C2 c2;
    11a4:       48 8d 05 b5 2b 00 00    lea    0x2bb5(%rip),%rax        # 3d60 <_ZTV2C2+0x10>
    11ab:       48 89 45 c0             mov    %rax,-0x40(%rbp)
        C3 c3;
    11af:       48 8d 05 92 2b 00 00    lea    0x2b92(%rip),%rax        # 3d48 <_ZTV2C3+0x10>
    11b6:       48 89 45 c8             mov    %rax,-0x38(%rbp)

        //静态绑定(编译时确定)
        c.func();
    11ba:       48 8d 45 be             lea    -0x42(%rbp),%rax
    11be:       48 89 c7                mov    %rax,%rdi
    11c1:       e8 d8 00 00 00          call   129e <_ZN1C4funcEv>
        c1.func();
    11c6:       48 8d 45 bf             lea    -0x41(%rbp),%rax
    11ca:       48 89 c7                mov    %rax,%rdi
    11cd:       e8 0a 01 00 00          call   12dc <_ZN2C14funcEv>
        c2.func();
    11d2:       48 8d 45 c0             lea    -0x40(%rbp),%rax
    11d6:       48 89 c7                mov    %rax,%rdi
    11d9:       e8 3c 01 00 00          call   131a <_ZN2C24funcEv>
        c3.func();
    11de:       48 8d 45 c8             lea    -0x38(%rbp),%rax
    11e2:       48 89 c7                mov    %rax,%rdi
    11e5:       e8 6e 01 00 00          call   1358 <_ZN2C34funcEv>

        C *pc = &c1;
    11ea:       48 8d 45 bf             lea    -0x41(%rbp),%rax
    11ee:       48 89 45 d8             mov    %rax,-0x28(%rbp)
        pc->func();             //静态绑定(编译时确定)
    11f2:       48 8b 45 d8             mov    -0x28(%rbp),%rax
    11f6:       48 89 c7                mov    %rax,%rdi
    11f9:       e8 a0 00 00 00          call   129e <_ZN1C4funcEv>

        C2 *pc2 = &c3;
    11fe:       48 8d 45 c8             lea    -0x38(%rbp),%rax
    1202:       48 89 45 e0             mov    %rax,-0x20(%rbp)
        pc2->func();            //动态绑定(运行时确定)
    1206:       48 8b 45 e0             mov    -0x20(%rbp),%rax
    120a:       48 8b 00                mov    (%rax),%rax
    120d:       48 8b 10                mov    (%rax),%rdx
    1210:       48 8b 45 e0             mov    -0x20(%rbp),%rax
    1214:       48 89 c7                mov    %rax,%rdi
    1217:       ff d2                   call   *%rdx


        pc = &c;                //静态绑定(编译时确定)
    1219:       48 8d 45 be             lea    -0x42(%rbp),%rax
    121d:       48 89 45 d8             mov    %rax,-0x28(%rbp)
        pc->func();
    1221:       48 8b 45 d8             mov    -0x28(%rbp),%rax
    1225:       48 89 c7                mov    %rax,%rdi
    1228:       e8 71 00 00 00          call   129e <_ZN1C4funcEv>

        C1 *pc1 = &c1;          //静态绑定(编译时确定)
    122d:       48 8d 45 bf             lea    -0x41(%rbp),%rax
    1231:       48 89 45 e8             mov    %rax,-0x18(%rbp)
        pc1->func();
    1235:       48 8b 45 e8             mov    -0x18(%rbp),%rax
    1239:       48 89 c7                mov    %rax,%rdi
    123c:       e8 9b 00 00 00          call   12dc <_ZN2C14funcEv>

        pc2 = &c2;              //动态绑定(运行时确定)
    1241:       48 8d 45 c0             lea    -0x40(%rbp),%rax
    1245:       48 89 45 e0             mov    %rax,-0x20(%rbp)
        pc2->func();
    1249:       48 8b 45 e0             mov    -0x20(%rbp),%rax
    124d:       48 8b 00                mov    (%rax),%rax
    1250:       48 8b 10                mov    (%rax),%rdx
    1253:       48 8b 45 e0             mov    -0x20(%rbp),%rax
    1257:       48 89 c7                mov    %rax,%rdi
    125a:       ff d2                   call   *%rdx

        C3 *pc3 = &c3;
    125c:       48 8d 45 c8             lea    -0x38(%rbp),%rax
    1260:       48 89 45 f0             mov    %rax,-0x10(%rbp)
        pc3->func();            //动态绑定(运行时确定)
    1264:       48 8b 45 f0             mov    -0x10(%rbp),%rax
    1268:       48 8b 00                mov    (%rax),%rax
    126b:       48 8b 10                mov    (%rax),%rdx
    126e:       48 8b 45 f0             mov    -0x10(%rbp),%rax
    1272:       48 89 c7                mov    %rax,%rdi
    1275:       ff d2                   call   *%rdx

        C4 c4;                  //定义在构造函数中的虚函数为静态绑定(编译时确定)
    1277:       48 8d 45 d0             lea    -0x30(%rbp),%rax
    127b:       48 89 c7                mov    %rax,%rdi
    127e:       e8 51 01 00 00          call   13d4 <_ZN2C4C1Ev>

        return 0;
    1283:       b8 00 00 00 00          mov    $0x0,%eax
}
    1288:       48 8b 55 f8             mov    -0x8(%rbp),%rdx
    128c:       64 48 2b 14 25 28 00    sub    %fs:0x28,%rdx
    1293:       00 00 
    1295:       74 05                   je     129c <main+0x113>
    1297:       e8 f4 fd ff ff          call   1090 <__stack_chk_fail@plt>
    129c:       c9                      leave
    129d:       c3                      ret

000000000000129e <_ZN1C4funcEv>:
                void func()
    129e:       f3 0f 1e fa             endbr64
    12a2:       55                      push   %rbp
    12a3:       48 89 e5                mov    %rsp,%rbp
    12a6:       48 83 ec 10             sub    $0x10,%rsp
    12aa:       48 89 7d f8             mov    %rdi,-0x8(%rbp)
                        std::cout << "C::func()" << std::endl;
    12ae:       48 8d 05 4f 0d 00 00    lea    0xd4f(%rip),%rax        # 2004 <_IO_stdin_used+0x4>
    12b5:       48 89 c6                mov    %rax,%rsi
    12b8:       48 8d 05 81 2d 00 00    lea    0x2d81(%rip),%rax        # 4040 <_ZSt4cout@GLIBCXX_3.4>
    12bf:       48 89 c7                mov    %rax,%rdi
    12c2:       e8 a9 fd ff ff          call   1070 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
    12c7:       48 8b 15 0a 2d 00 00    mov    0x2d0a(%rip),%rdx        # 3fd8 <_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GLIBCXX_3.4>
    12ce:       48 89 d6                mov    %rdx,%rsi
    12d1:       48 89 c7                mov    %rax,%rdi
    12d4:       e8 a7 fd ff ff          call   1080 <_ZNSolsEPFRSoS_E@plt>
                }
    12d9:       90                      nop
    12da:       c9                      leave
    12db:       c3                      ret

00000000000012dc <_ZN2C14funcEv>:
                void func()
    12dc:       f3 0f 1e fa             endbr64
    12e0:       55                      push   %rbp
    12e1:       48 89 e5                mov    %rsp,%rbp
    12e4:       48 83 ec 10             sub    $0x10,%rsp
    12e8:       48 89 7d f8             mov    %rdi,-0x8(%rbp)
                        std::cout << "C1::func()" << std::endl;
    12ec:       48 8d 05 1b 0d 00 00    lea    0xd1b(%rip),%rax        # 200e <_IO_stdin_used+0xe>
    12f3:       48 89 c6                mov    %rax,%rsi
    12f6:       48 8d 05 43 2d 00 00    lea    0x2d43(%rip),%rax        # 4040 <_ZSt4cout@GLIBCXX_3.4>
    12fd:       48 89 c7                mov    %rax,%rdi
    1300:       e8 6b fd ff ff          call   1070 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
    1305:       48 8b 15 cc 2c 00 00    mov    0x2ccc(%rip),%rdx        # 3fd8 <_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GLIBCXX_3.4>
    130c:       48 89 d6                mov    %rdx,%rsi
    130f:       48 89 c7                mov    %rax,%rdi
    1312:       e8 69 fd ff ff          call   1080 <_ZNSolsEPFRSoS_E@plt>
                }
    1317:       90                      nop
    1318:       c9                      leave
    1319:       c3                      ret

000000000000131a <_ZN2C24funcEv>:
                virtual void func()
    131a:       f3 0f 1e fa             endbr64
    131e:       55                      push   %rbp
    131f:       48 89 e5                mov    %rsp,%rbp
    1322:       48 83 ec 10             sub    $0x10,%rsp
    1326:       48 89 7d f8             mov    %rdi,-0x8(%rbp)
                        std::cout << "C2:func()" << std::endl;
    132a:       48 8d 05 e8 0c 00 00    lea    0xce8(%rip),%rax        # 2019 <_IO_stdin_used+0x19>
    1331:       48 89 c6                mov    %rax,%rsi
    1334:       48 8d 05 05 2d 00 00    lea    0x2d05(%rip),%rax        # 4040 <_ZSt4cout@GLIBCXX_3.4>
    133b:       48 89 c7                mov    %rax,%rdi
    133e:       e8 2d fd ff ff          call   1070 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
    1343:       48 8b 15 8e 2c 00 00    mov    0x2c8e(%rip),%rdx        # 3fd8 <_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GLIBCXX_3.4>
    134a:       48 89 d6                mov    %rdx,%rsi
    134d:       48 89 c7                mov    %rax,%rdi
    1350:       e8 2b fd ff ff          call   1080 <_ZNSolsEPFRSoS_E@plt>
                }
    1355:       90                      nop
    1356:       c9                      leave
    1357:       c3                      ret

0000000000001358 <_ZN2C34funcEv>:
                void func()
    1358:       f3 0f 1e fa             endbr64
    135c:       55                      push   %rbp
    135d:       48 89 e5                mov    %rsp,%rbp
    1360:       48 83 ec 10             sub    $0x10,%rsp
    1364:       48 89 7d f8             mov    %rdi,-0x8(%rbp)
                        std::cout << "C3::func()" << std::endl;
    1368:       48 8d 05 b4 0c 00 00    lea    0xcb4(%rip),%rax        # 2023 <_IO_stdin_used+0x23>
    136f:       48 89 c6                mov    %rax,%rsi
    1372:       48 8d 05 c7 2c 00 00    lea    0x2cc7(%rip),%rax        # 4040 <_ZSt4cout@GLIBCXX_3.4>
    1379:       48 89 c7                mov    %rax,%rdi
    137c:       e8 ef fc ff ff          call   1070 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
    1381:       48 8b 15 50 2c 00 00    mov    0x2c50(%rip),%rdx        # 3fd8 <_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GLIBCXX_3.4>
    1388:       48 89 d6                mov    %rdx,%rsi
    138b:       48 89 c7                mov    %rax,%rdi
    138e:       e8 ed fc ff ff          call   1080 <_ZNSolsEPFRSoS_E@plt>
                }
    1393:       90                      nop
    1394:       c9                      leave
    1395:       c3                      ret

0000000000001396 <_ZN2C44funcEv>:
                virtual void func()
    1396:       f3 0f 1e fa             endbr64
    139a:       55                      push   %rbp
    139b:       48 89 e5                mov    %rsp,%rbp
    139e:       48 83 ec 10             sub    $0x10,%rsp
    13a2:       48 89 7d f8             mov    %rdi,-0x8(%rbp)
                        std::cout << "C4::func()" << std::endl; 
    13a6:       48 8d 05 81 0c 00 00    lea    0xc81(%rip),%rax        # 202e <_IO_stdin_used+0x2e>
    13ad:       48 89 c6                mov    %rax,%rsi
    13b0:       48 8d 05 89 2c 00 00    lea    0x2c89(%rip),%rax        # 4040 <_ZSt4cout@GLIBCXX_3.4>
    13b7:       48 89 c7                mov    %rax,%rdi
    13ba:       e8 b1 fc ff ff          call   1070 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
    13bf:       48 8b 15 12 2c 00 00    mov    0x2c12(%rip),%rdx        # 3fd8 <_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GLIBCXX_3.4>
    13c6:       48 89 d6                mov    %rdx,%rsi
    13c9:       48 89 c7                mov    %rax,%rdi
    13cc:       e8 af fc ff ff          call   1080 <_ZNSolsEPFRSoS_E@plt>
                }
    13d1:       90                      nop
    13d2:       c9                      leave
    13d3:       c3                      ret

00000000000013d4 <_ZN2C4C1Ev>:
                C4()
    13d4:       f3 0f 1e fa             endbr64
    13d8:       55                      push   %rbp
    13d9:       48 89 e5                mov    %rsp,%rbp
    13dc:       48 83 ec 10             sub    $0x10,%rsp
    13e0:       48 89 7d f8             mov    %rdi,-0x8(%rbp)
                {
    13e4:       48 8d 15 45 29 00 00    lea    0x2945(%rip),%rdx        # 3d30 <_ZTV2C4+0x10>
    13eb:       48 8b 45 f8             mov    -0x8(%rbp),%rax
    13ef:       48 89 10                mov    %rdx,(%rax)
                        std::cout << "C4()" << std::endl;
    13f2:       48 8d 05 40 0c 00 00    lea    0xc40(%rip),%rax        # 2039 <_IO_stdin_used+0x39>
    13f9:       48 89 c6                mov    %rax,%rsi
    13fc:       48 8d 05 3d 2c 00 00    lea    0x2c3d(%rip),%rax        # 4040 <_ZSt4cout@GLIBCXX_3.4>
    1403:       48 89 c7                mov    %rax,%rdi
    1406:       e8 65 fc ff ff          call   1070 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
    140b:       48 8b 15 c6 2b 00 00    mov    0x2bc6(%rip),%rdx        # 3fd8 <_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GLIBCXX_3.4>
    1412:       48 89 d6                mov    %rdx,%rsi
    1415:       48 89 c7                mov    %rax,%rdi
    1418:       e8 63 fc ff ff          call   1080 <_ZNSolsEPFRSoS_E@plt>
                        func();
    141d:       48 8b 45 f8             mov    -0x8(%rbp),%rax
    1421:       48 89 c7                mov    %rax,%rdi
    1424:       e8 6d ff ff ff          call   1396 <_ZN2C44funcEv>
                }
    1429:       90                      nop
    142a:       c9                      leave
    142b:       c3                      ret

Disassembly of section .fini:

000000000000142c <_fini>:
    142c:       f3 0f 1e fa             endbr64
    1430:       48 83 ec 08             sub    $0x8,%rsp
    1434:       48 83 c4 08             add    $0x8,%rsp
    1438:       c3                      ret

demo2:

        类定义虚函数在编译时产生vftable函数表(类中添加vptr指向vftable),vftable存储RTTI指针和虚函数地址,运行时将虚函数表加载到.rodata

结构图:

代码示例:

CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 3.28)                            #最低版本要求
 
SET(CMAKE_CXX_COMPILER "g++-11")                                #设置g++编译器
 
PROJECT(CLASS)                                                  #设置工程名
 
MESSAGE(STATUS "CPP test")                                      #打印消息
 
ADD_EXECUTABLE(pro test.cpp)                                    #生成可执行文件

run.sh

#!/bin/bash
 
if [ -f ./Makefile ]
then
        make clean
fi
 
cmake .
 
make
 
echo "---------------------------------"
 
./pro

g++ test.cpp -o test -g

objdump -S test > test.dis

clean.sh

rm -rf CMakeCache.txt CMakeFiles Makefile cmake_install.cmake *.o pro test test.dis

test.cpp

#include <iostream>

class People
{
        public:
                People(std::string name):name(name){};
                virtual void print_sex() = 0;
        protected:
                std::string name;
};

class Man : public People
{
        public:
                Man(std::string name):People(name){};
                void print_sex() 
                {
                        std::cout << "man" << std::endl;
                }
};

class Woman : public People
{
        public:
                Woman(std::string name):People(name){};
                void print_sex()
                {
                        std::cout << "woman" << std::endl;
                }
};

int main()
{
        People *p1 = new Man("xiaoMing");
        People *p2 = new Woman("xiaoHua");

        //交换vptr
        int *m = (int*)p1;
        int *w = (int*)p2;
        int tmp = m[0];
        m[0] = w[0];
        w[0] = tmp;

        p1->print_sex();
        p2->print_sex();
        delete p1;
        delete p2;

        return 0;
}

 结果示例:

demo3: 

        成员方法调用在运行阶段确定,默认参数和访问权限在编译阶段(字面判断调用)确定
        静态绑定时运行时确定,动态绑定时运行时确定

结构图:

代码示例:

CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 3.28)                            #最低版本要求
 
SET(CMAKE_CXX_COMPILER "g++-11")                                #设置g++编译器
 
PROJECT(CLASS)                                                  #设置工程名
 
MESSAGE(STATUS "CPP test")                                      #打印消息
 
ADD_EXECUTABLE(pro test.cpp)                                    #生成可执行文件

run.sh

#!/bin/bash
 
if [ -f ./Makefile ]
then
        make clean
fi
 
cmake .
 
make
 
echo "---------------------------------"
 
./pro

g++ test.cpp -o test -g

objdump -S test > test.dis

clean.sh

rm -rf CMakeCache.txt CMakeFiles Makefile cmake_install.cmake *.o pro test test.dis

test.cpp

#include <iostream>
#include <cstring>

class C
{
        public:
                virtual void print_num(int num = 1)
                {
                        std::cout << "num:" << num << std::endl;
                }

};

class C1 : public C
{
        private:
                void print_num(int num = 2)
                {
                        std::cout << "num:" << num << std::endl;
                }
};

class D
{
        public:
                D()
                {
                        std::cout << "D()" << std::endl; 
                        clear();
                };

                void clear()
                {
                        memset(this,0,sizeof(*this));
                }

                virtual void print_info()
                {
                        std::cout << "D::print_info" << std::endl;
                }
};

class D1 : public D
{
        public:
                D1()
                {
                        std::cout << "D1()" << std::endl;
                }

                void print_info()
                {
                        std::cout << "D1::print_info" << std::endl;
                }
};

int main()
{
        //默认参数压栈在编译时完成(压入默认参数10),运行时调用函数执行(调用C1::print_num)
        //权限(public,proteated,private)是在编译时确定(字面判断调用)
        //静态绑定时运行时确定,动态绑定时运行时确定
        C *c = new C1();
        c->print_num();
        delete c;

        //基类构造和派生类构造时clear清理了调用基类构造的vptr,派生类构造未清理
        /*
         * D *d = new D();
         * d->print_info();
         * delete d;
         */

        D1 *d1 = new D1();
        d1->print_info();
        delete d1;

        return 0;
}

结果示例:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值