【C++】Geekband-专题二:虚指针和内存分配

1. 传统继承类的设计

  1. static void print_object(const char* name, void* this_, size_t size) {
  2. void** ugly = reinterpret_cast<void**>(this_);
  3. size_t i;
  4. printf("created %s at address %p of size %zu ", name, this_, size);
  5. for(i = 0 ; i < size / sizeof(void*) ; i++) {
  6. printf(" pointer[%zu] == %p ", i, ugly[i]);
  7. }
  8. cout << "-------------------------------"<<endl;
  9. }
  10. class A {
  11. public:
  12. long iA;
  13. long iAA;
  14. A ():iA (1), iAA(10) {print_object(__FUNCTION__, this, sizeof(*this));
  15. }
  16. virtual void f() { cout << "A::f()" << endl; }
  17. virtual void g() { cout << "A::g()" << endl; }
  18. virtual void h() { cout << "A::h()" << endl; }
  19. };
  20. class B : public A {
  21. public:
  22. long iB;
  23. B():iB(2) {
  24. print_object(__FUNCTION__, this, sizeof(*this));
  25. }
  26. virtual void f() { cout << "B::f()" << endl; }
  27. virtual void g_B() { cout << "B::g_B()" << endl; }
  28. virtual void h_B() { cout << "B::h_B()" << endl; }
  29. };
  30. class C : public B{
  31. public:
  32. long iC;
  33. C():iC(3) {
  34. print_object(__FUNCTION__, this, sizeof(*this));
  35. }
  36. virtual void f() { cout << "C::f()" << endl; }
  37. virtual void g_B() { cout << "C::g_B()" << endl; }
  38. virtual void h_C() { cout << "C::h_C()" << endl; }
  39. };
  • A、B、C依次继承
  • 并在构造过程中通过print_object输出构建信息

2. 构造Class C,并通过指针来一次访问内容或调用函数

  1. int main()
  2. {
  3. typedef void(*Fun)(void);
  4. long** pVtab = nullptr;
  5. Fun pFun = nullptr;
  6. C c;
  7. pVtab = (long**)&c;
  8. long *cAsLong = (long *)&c;
  9. cout << "C::vptr memory address is " << &cAsLong[0] <<endl;
  10. cout << "[0] C::_vptr->" << endl;
  11. cout << " No. Memory Address Value Function" << endl;
  12. for (int i=0; (Fun)pVtab[0][i] != nullptr; i++){
  13. pFun = (Fun)pVtab[0][i];
  14. cout << " ["<<i<<"] ";
  15. cout << " " << &pVtab[0][i]<<" ";;
  16. cout << " " << (void *)pVtab[0][i]<<" ";;
  17. pFun();
  18. }
  19. cout << " ----------------------------------" << endl;
  20. cout << "[0] addr = " << &pVtab[0] << " ";
  21. cout << "value = " << pVtab[0] << endl;
  22. cout << "[1] addr = "<< &pVtab[1] << " ";
  23. cout << "value = " << pVtab[1] << " ";
  24. cout << "A.iA = " << *((long *) &pVtab[1] )<< endl;
  25. cout << c.iA << endl;
  26. cout << "[2] addr = " << &pVtab[2] << " ";
  27. cout << "value = " << pVtab[2] << " ";
  28. cout << "A.iAA = " << *((long *) &pVtab[2]) << endl;
  29. cout << "[3] addr = " << &pVtab[3] << " ";
  30. cout << "value = " << pVtab[3] << " ";
  31. cout << "B.iB = " << *((long *) &pVtab[3]) << endl;
  32. cout << "[4] addr = " << &pVtab[4] << " ";
  33. cout << "value = " << pVtab[4] << " ";
  34. cout << "C.iC = " << *((long *) &pVtab[4]) << endl;
  35. return 0;
  • pVtab用于显示虚表的位置,并用于后续的直接调用
  • 通过循环,一次输出虚表中各个成员的地址和对应的存储内容
  • 最后,通过直接调用相应的存储内容来调用成员或调用函数。

3. gdb的使用方法

  • 编译过程
  1. g++ -g -o test.cpp test
  • gdb运行程序
  1. (gdb) r
  • gdb中设置断点
  1. (gdb) break line_number
  • gdb中查询虚表
  1. (gdb) info vtbl c
  • gdb中查询内存内容 - 选择输出的格式
  1. (gdb) x /5xg 0xfffffffd70
  1. (gdb) x /32xg 0x401440

4. 具体逻辑关系见下图

http://7xlos6.com1.z0.glb.clouddn.com/%E6%9D%82.png
杂.png

原文地址:https://www.cnblogs.com/kongww/p/5419954.html