C++ 疑问
本帖最后由 chenzhanyiczy 于 2011-04-13 17:16 编辑
#include <iostream>
using namespace std;
class base{
public:
virtual ~base(){}
};
class base2{
public:
virtual ~base2(){}
};
class derived:public base2,public base{
public:
virtual ~derived(){cout<<"this is ~derived"<<endl;}
};
int main(){
derived dd;
cout<<"dd's address is :"<<&dd<<endl; -->1
void (*pf)()=(void (*)())*((int*)*(int*)(&dd));
pf();
}
为什么会有段错误?而去掉1就没有段错误。
先说说个人的看法:段错误当然是访问了不可访问的内存引起的。但就这个例子,就不明白什么情况引起的。
虽然在析构函数中,会默认有个this指针,无论这个this指向哪里,可这个this指向的内容根本没有访问到,
按说不会发生什么段错误,不知道编译器在派生类析构函数中做了什么手脚。回头只能看看汇编了。
另外:
#include <iostream>
using namespace std;
class base{
public:
virtual void foo(){}
};
class base2{
public:
virtual void foo2(){}
};
class derived:public base2,public base{
public:
virtual void foo(){cout<<"this is foo"<<endl;}
virtual void foo2(){cout<<"this is foo2"<<endl;}
};
int main(){
derived dd;
cout<<"dd's address is :"<<&dd<<endl; // -->1
void (*pf)()=(void (*)())*((int*)*(int*)(&dd));
pf();
}
上面这段代码无论有没有 1 都是没有问题的
编译器是:gcc 4.1.2 20070626
所以问题重点在于编译器对虚析构函数做了什么手脚才会造成段错误的。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
本帖最后由 zhujiang73 于 2011-04-13 16:06 编辑
void (*pf)() 不能用在类内的非静态函数。
回复 2# zhujiang73
对。当然也是可以的。
这里的问题在于:编译器对析构函数做了什么附加动作。而类似*this等动作导致段错误。当然这只是怀疑的情况之一。
不过就这个例子而言,个人觉得编译器不需要对析构函数做什么附加动作,即使做了,也不会出现类似*this等动作。真奇怪。
我认为目前这个 void (*pf)() 里是虚函数表的地址,虚函数表里的内容才是函数的真实地址。
回复 4# zhujiang73
void (*pf)()=(void (*)())*((int*)*(int*)(&dd));
pf的值已经是函数的真实地址了,这个可以不用怀疑。仔细看看。
但问题的重点不在于此。
不知你用的什么编译器,虚表的第一项不一定是第一个虚函数的指针,也有可能是指向类型信息的指针(就是typeid和dynamic_cast要用到的那个),也有可能是多重继承时用来调整指针的偏移量.
这么多括号没看清,不过虚表应该不会这么简单。
应该是有偏移量,这个在我这可以。 “gcc version 4.5.2 (Debian 4.5.2-”
复制代码
回复 8# zhujiang73
这个不行的,段错误的。你确定运行正确?
更新了1楼的描述