更改虚函数的vtbl表的问题 (在线)

时间:2022-06-19 18:27:47
请看下面的代码,我把a的vtbl表改成了b的vtbl表(这样改很无聊吧),再用aa类的指针l指向了a的地址,l->ff1()到达了我预期的目标,但为什么a.ff1()还是不变,这和我上次提的那个常量替换的帖有点象哈  
 常量替换帖  http://topic.csdn.net/u/20081213/17/8f4b5a1d-e6bf-43fc-98d9-ccd25777f4a9.html


#include <iostream>
#include <string.h> 
using namespace std;
class aa
{
public:
virtual void ff1()
{
cout<<"111111111111"<<endl;
}
};

class bb 
{
  public:
virtual void ff2()
{
cout<<"22222222222"<<endl;
}
};
void main()
{
aa a;
bb b;
aa* l=&a;
a.ff1();                    //换之前, 输出了“111111111111111”
l->ff1();                   //换之前, 输出了“111111111111111”

cout<<*((int*)&a)<<endl;    //a中vtbl表的地址
cout<<*((int*)&b)<<endl; //b中vtbl表的地址

memcpy(&a,&b,4);           //vtbl表的地址交换

cout<<*((int*)&a)<<endl;   //a和b的vtbl表一样了
cout<<*((int*)&b)<<endl;

l->ff1();                   //因为换了,所以输出了“22222222222222”
a.ff1();     //为什么输出了“111111111111111”
 
system("pause");
}

16 个解决方案

#2


虚函数,多态,只对指针和引用有效

#3


引用 2 楼 Chiyer 的回复:
虚函数,多态,只对指针和引用有效

up
不过还是得学习楼主的钻研精神  呵呵 

#4


哦 引用的我试过了,果然也是输出“22222222222”,我就想不通了,编译器怎么这么牛B,我把对象里的内容改了,他还能找到原来的函数,想不通想不通

#5


不明白,期待高手解决 !!!

#6


哎  可惜汇编学的很垃圾,不然可以到汇编码里去看看,后来的朋友把这个代码的汇编码解释一下好么,谢谢!!

#7


up

#8


aa a;
a.ff1();

当你这样去调用的函数的时候,编译器是在编译的时候就根据a的类型aa,确定了它要调用的函数ff1的地址
但如果是指针或许引用,则编译器编译的时候不绑定调用的函数,而是在运行的时候才通过虚表去查,在去调用具体的函数

#9


引用 8 楼 Chiyer 的回复:
aa a; 
a.ff1(); 

当你这样去调用的函数的时候,编译器是在编译的时候就根据a的类型aa,确定了它要调用的函数ff1的地址 
但如果是指针或许引用,则编译器编译的时候不绑定调用的函数,而是在运行的时候才通过虚表去查,在去调用具体的函数

哦 原来是这样,也就是说编译器看到a.ff1()首先想到的是去aa类里面去找ff(),怪不的改了vtbl也没用,原来根本就没访问这里啊

还想问问星羽,这些是哪方面的知识啊,我看的书里面都不讲这些

#10


引用 6 楼 baifanmvp 的回复:
哎  可惜汇编学的很垃圾,不然可以到汇编码里去看看,后来的朋友把这个代码的汇编码解释一下好么,谢谢!!


跟汇编没有关系的
你的虚表确实一个更换了
但是调用虚表就必须用引用或者指针
对象是不会用到虚表的
会直接用一个在全局空间的函数的地址指针
理解?

#11


引用 10 楼 ztz0223 的回复:
引用 6 楼 baifanmvp 的回复:
哎  可惜汇编学的很垃圾,不然可以到汇编码里去看看,后来的朋友把这个代码的汇编码解释一下好么,谢谢!! 
 

跟汇编没有关系的 
你的虚表确实一个更换了 
但是调用虚表就必须用引用或者指针 
对象是不会用到虚表的 
会直接用一个在全局空间的函数的地址指针 
理解?

恩  了解了,谢谢

#12


学习

#13


引用 4 楼 baifanmvp 的回复:
哦 引用的我试过了,果然也是输出“22222222222”,我就想不通了,编译器怎么这么牛B,我把对象里的内容改了,他还能找到原来的函数,想不通想不通



具体调用那个函数和如何调用关系很大。 一种是动态确定(RTTI),一种静态绑定
如果直接使用实例,那么编译器自然就可以认为你使用的就是确定的类型,(因为它不nb,不知道你会改变他的vptr),静态绑定。
如果使用的指针 or 引用,编译器就好衡量,这个确定的类型到底是什么,于是,对于所有的virturl使用vtbl里面的数值。

不过楼主那种转法没有可移植性的,作为学习完全支持,不建议实际使用。就是可以移植,也会让其他人很郁闷的。

#14


用一句耳熟能详的话:没有后绑定,就没有多态。

#15


顶这个,也想学习学习!

引用 9 楼 baifanmvp 的回复:
引用 8 楼 Chiyer 的回复:
aa a; 
a.ff1(); 

当你这样去调用的函数的时候,编译器是在编译的时候就根据a的类型aa,确定了它要调用的函数ff1的地址 
但如果是指针或许引用,则编译器编译的时候不绑定调用的函数,而是在运行的时候才通过虚表去查,在去调用具体的函数 
 
哦 原来是这样,也就是说编译器看到a.ff1()首先想到的是去aa类里面去找ff(),怪不的改了vtbl也没用,原来根本就没访问这里啊 

还想问问星羽,这些…

#16


不错的尝试方法,可以增长些见识,学习了

#1


#2


虚函数,多态,只对指针和引用有效

#3


引用 2 楼 Chiyer 的回复:
虚函数,多态,只对指针和引用有效

up
不过还是得学习楼主的钻研精神  呵呵 

#4


哦 引用的我试过了,果然也是输出“22222222222”,我就想不通了,编译器怎么这么牛B,我把对象里的内容改了,他还能找到原来的函数,想不通想不通

#5


不明白,期待高手解决 !!!

#6


哎  可惜汇编学的很垃圾,不然可以到汇编码里去看看,后来的朋友把这个代码的汇编码解释一下好么,谢谢!!

#7


up

#8


aa a;
a.ff1();

当你这样去调用的函数的时候,编译器是在编译的时候就根据a的类型aa,确定了它要调用的函数ff1的地址
但如果是指针或许引用,则编译器编译的时候不绑定调用的函数,而是在运行的时候才通过虚表去查,在去调用具体的函数

#9


引用 8 楼 Chiyer 的回复:
aa a; 
a.ff1(); 

当你这样去调用的函数的时候,编译器是在编译的时候就根据a的类型aa,确定了它要调用的函数ff1的地址 
但如果是指针或许引用,则编译器编译的时候不绑定调用的函数,而是在运行的时候才通过虚表去查,在去调用具体的函数

哦 原来是这样,也就是说编译器看到a.ff1()首先想到的是去aa类里面去找ff(),怪不的改了vtbl也没用,原来根本就没访问这里啊

还想问问星羽,这些是哪方面的知识啊,我看的书里面都不讲这些

#10


引用 6 楼 baifanmvp 的回复:
哎  可惜汇编学的很垃圾,不然可以到汇编码里去看看,后来的朋友把这个代码的汇编码解释一下好么,谢谢!!


跟汇编没有关系的
你的虚表确实一个更换了
但是调用虚表就必须用引用或者指针
对象是不会用到虚表的
会直接用一个在全局空间的函数的地址指针
理解?

#11


引用 10 楼 ztz0223 的回复:
引用 6 楼 baifanmvp 的回复:
哎  可惜汇编学的很垃圾,不然可以到汇编码里去看看,后来的朋友把这个代码的汇编码解释一下好么,谢谢!! 
 

跟汇编没有关系的 
你的虚表确实一个更换了 
但是调用虚表就必须用引用或者指针 
对象是不会用到虚表的 
会直接用一个在全局空间的函数的地址指针 
理解?

恩  了解了,谢谢

#12


学习

#13


引用 4 楼 baifanmvp 的回复:
哦 引用的我试过了,果然也是输出“22222222222”,我就想不通了,编译器怎么这么牛B,我把对象里的内容改了,他还能找到原来的函数,想不通想不通



具体调用那个函数和如何调用关系很大。 一种是动态确定(RTTI),一种静态绑定
如果直接使用实例,那么编译器自然就可以认为你使用的就是确定的类型,(因为它不nb,不知道你会改变他的vptr),静态绑定。
如果使用的指针 or 引用,编译器就好衡量,这个确定的类型到底是什么,于是,对于所有的virturl使用vtbl里面的数值。

不过楼主那种转法没有可移植性的,作为学习完全支持,不建议实际使用。就是可以移植,也会让其他人很郁闷的。

#14


用一句耳熟能详的话:没有后绑定,就没有多态。

#15


顶这个,也想学习学习!

引用 9 楼 baifanmvp 的回复:
引用 8 楼 Chiyer 的回复:
aa a; 
a.ff1(); 

当你这样去调用的函数的时候,编译器是在编译的时候就根据a的类型aa,确定了它要调用的函数ff1的地址 
但如果是指针或许引用,则编译器编译的时候不绑定调用的函数,而是在运行的时候才通过虚表去查,在去调用具体的函数 
 
哦 原来是这样,也就是说编译器看到a.ff1()首先想到的是去aa类里面去找ff(),怪不的改了vtbl也没用,原来根本就没访问这里啊 

还想问问星羽,这些…

#16


不错的尝试方法,可以增长些见识,学习了