support bazel complie this project and format code.
This commit is contained in:
8
basic_content/vptr_vtable/BUILD
Normal file
8
basic_content/vptr_vtable/BUILD
Normal file
@@ -0,0 +1,8 @@
|
||||
# please run `bazel run basic_content/vptr_vtable:vptr1`
|
||||
load("@rules_cc//cc:defs.bzl", "cc_binary")
|
||||
|
||||
cc_binary(
|
||||
name = "vptr1",
|
||||
srcs = ["vptr1.cpp"],
|
||||
copts = ["-std=c++11"]
|
||||
)
|
@@ -1,12 +1,3 @@
|
||||
/**
|
||||
* @file vptr1.cpp
|
||||
* @brief C++虚函数vptr和vtable
|
||||
* 编译:g++ -g -o vptr vptr1.cpp -std=c++11
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-07-20
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
using namespace std;
|
||||
@@ -16,90 +7,75 @@ using namespace std;
|
||||
*/
|
||||
typedef void (*Fun)();
|
||||
|
||||
|
||||
/**
|
||||
* @brief 基类
|
||||
*/
|
||||
class Base
|
||||
{
|
||||
public:
|
||||
Base(){};
|
||||
virtual void fun1()
|
||||
{
|
||||
cout << "Base::fun1()" << endl;
|
||||
}
|
||||
virtual void fun2()
|
||||
{
|
||||
cout << "Base::fun2()" << endl;
|
||||
}
|
||||
virtual void fun3(){}
|
||||
~Base(){};
|
||||
class Base {
|
||||
public:
|
||||
Base(){};
|
||||
virtual void fun1() { cout << "Base::fun1()" << endl; }
|
||||
virtual void fun2() { cout << "Base::fun2()" << endl; }
|
||||
virtual void fun3() {}
|
||||
~Base(){};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 派生类
|
||||
*/
|
||||
class Derived: public Base
|
||||
{
|
||||
public:
|
||||
Derived(){};
|
||||
void fun1()
|
||||
{
|
||||
cout << "Derived::fun1()" << endl;
|
||||
}
|
||||
void fun2()
|
||||
{
|
||||
cout << "DerivedClass::fun2()" << endl;
|
||||
}
|
||||
~Derived(){};
|
||||
class Derived : public Base {
|
||||
public:
|
||||
Derived(){};
|
||||
void fun1() { cout << "Derived::fun1()" << endl; }
|
||||
void fun2() { cout << "DerivedClass::fun2()" << endl; }
|
||||
~Derived(){};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取vptr地址与func地址,vptr指向的是一块内存,这块内存存放的是虚函数地址,这块内存就是我们所说的虚表
|
||||
* @brief
|
||||
* 获取vptr地址与func地址,vptr指向的是一块内存,这块内存存放的是虚函数地址,这块内存就是我们所说的虚表
|
||||
*
|
||||
* @param obj
|
||||
* @param offset
|
||||
*
|
||||
* @return
|
||||
* @return
|
||||
*/
|
||||
Fun getAddr(void* obj,unsigned int offset)
|
||||
{
|
||||
cout<<"======================="<<endl;
|
||||
void* vptr_addr = (void *)*(unsigned long *)obj; //64位操作系统,占8字节,通过*(unsigned long *)obj取出前8字节,即vptr指针
|
||||
printf("vptr_addr:%p\n",vptr_addr);
|
||||
Fun getAddr(void *obj, unsigned int offset) {
|
||||
cout << "=======================" << endl;
|
||||
void *vptr_addr =
|
||||
(void *)*(unsigned long *)obj; // 64位操作系统,占8字节,通过*(unsigned
|
||||
// long *)obj取出前8字节,即vptr指针
|
||||
printf("vptr_addr:%p\n", vptr_addr);
|
||||
|
||||
/**
|
||||
* @brief 通过vptr指针访问virtual table,因为虚表中每个元素(虚函数指针)在64位编译器下是8个字节,因此通过*(unsigned long *)vptr_addr取出前8字节,
|
||||
* 后面加上偏移量就是每个函数的地址!
|
||||
*/
|
||||
void* func_addr = (void *)*((unsigned long *)vptr_addr+offset);
|
||||
printf("func_addr:%p\n",func_addr);
|
||||
return (Fun)func_addr;
|
||||
/**
|
||||
* @brief 通过vptr指针访问virtual
|
||||
* table,因为虚表中每个元素(虚函数指针)在64位编译器下是8个字节,因此通过*(unsigned
|
||||
* long *)vptr_addr取出前8字节, 后面加上偏移量就是每个函数的地址!
|
||||
*/
|
||||
void *func_addr = (void *)*((unsigned long *)vptr_addr + offset);
|
||||
printf("func_addr:%p\n", func_addr);
|
||||
return (Fun)func_addr;
|
||||
}
|
||||
int main(void)
|
||||
{
|
||||
Base ptr;
|
||||
Derived d;
|
||||
Base *pt = new Derived(); // 基类指针指向派生类实例
|
||||
Base &pp = ptr; // 基类引用指向基类实例
|
||||
Base &p = d; // 基类引用指向派生类实例
|
||||
cout<<"基类对象直接调用"<<endl;
|
||||
ptr.fun1();
|
||||
cout<<"基类引用指向基类实例"<<endl;
|
||||
pp.fun1();
|
||||
cout<<"基类指针指向派生类实例并调用虚函数"<<endl;
|
||||
pt->fun1();
|
||||
cout<<"基类引用指向派生类实例并调用虚函数"<<endl;
|
||||
p.fun1();
|
||||
int main(void) {
|
||||
Base ptr;
|
||||
Derived d;
|
||||
Base *pt = new Derived(); // 基类指针指向派生类实例
|
||||
Base &pp = ptr; // 基类引用指向基类实例
|
||||
Base &p = d; // 基类引用指向派生类实例
|
||||
cout << "基类对象直接调用" << endl;
|
||||
ptr.fun1();
|
||||
cout << "基类引用指向基类实例" << endl;
|
||||
pp.fun1();
|
||||
cout << "基类指针指向派生类实例并调用虚函数" << endl;
|
||||
pt->fun1();
|
||||
cout << "基类引用指向派生类实例并调用虚函数" << endl;
|
||||
p.fun1();
|
||||
|
||||
// 手动查找vptr 和 vtable
|
||||
Fun f1 = getAddr(pt, 0);
|
||||
(*f1)();
|
||||
Fun f2 = getAddr(pt, 1);
|
||||
(*f2)();
|
||||
|
||||
// 手动查找vptr 和 vtable
|
||||
Fun f1 = getAddr(pt, 0);
|
||||
(*f1)();
|
||||
Fun f2 = getAddr(pt, 1);
|
||||
(*f2)();
|
||||
|
||||
delete pt;
|
||||
return 0;
|
||||
delete pt;
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user