u011274109
luike
2017-06-24 05:47

C++ 虚函数表指针vptr什么情况下被改变?

  • c++
  • 编译器
  • dll
  • 虚函数表
  • 指针
我们知道虚函数表在编译时期被确定,虚表指针vptr在程序run time时在类对象构造函数执行期间被初始化,那它可能在什么情况下会被修改呢?
我现在知道在派生类对象构造时其会被修改;那除了这种情况之外还有什么场景可能会导致vptr被改变吗?
DLL导出场景下,比如这种:
Test.dll 
Test.dll中宏定义了 TEST_EXPORTS

#ifdef TEST_EXPORTS
#define TEST_API __declspec(dllexport)
#else
#define TEST_API __declspec(dllimport)
#endif
class TEST_API CBase
{
public:
CBase();
virtual void A4 ();
virtual void A5 ();
virtual void A6 ();
};
CBase::CBase()
{
cout<<"Test Conc"<<endl;
}

void CBase::A4()
{
cout<<"Test A4"<<endl;
}

void CBase::A5()
{
cout<<"Test A5"<<endl;
}

void CBase::A6()
{
cout<<"Test A6"<<endl;
}

Main.exe
Main.exe中未宏定义TESTTWO_EXPORTS

#ifdef TESTTWO_EXPORTS
#define TESTTWO_API __declspec(dllexport)
#else
#define TESTTWO_API __declspec(dllimport)
#endif

class TESTTWO_API CBase
{
public:
CBase();
virtual void A1 ();
virtual void A2 ();
virtual void A3 ();
};

CBase::CBase()
{
cout<<"Main Conc"<<endl;
}

void CBase::A1()
{
cout<<"Main A1"<<endl;
}

void CBase::A2()
{
cout<<"Main A2"<<endl;
}

void CBase::A3()
{
cout<<"Main A3"<<endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
CBase *baseObj = new CBase;
baseObj->A1();
return 0;
}
最终我的输出结果是:
Main Conc
Test A4
而不是
Main Conc
Main A1 呢?
这点我很不能理解,讲道理说,虽然我MAIN.EXE中的CBase被我声明成了导入的,但是,baseObj调用的构造函数实实在在MAIN.EXE中的CBase的构造函数,那为啥vptr所指向虚表却是Test.DLL中的呢?通过调试模块查看各模块的虚拟内存地址也可以发现baseObj中的虚表地址所在的模块是Test.DLL中。vptr确实指向Test.dll中的虚表的话,那baseObj->A1()输出Test A4确实是正确,可为什么vptr会指向Test.dll中的虚表?tell me why?!难道仅仅是因为Main.exe中CBase被定义成导入的,所以编译器优先从外部符号中寻找吗?!这是什么道理?讲道理啊!
小弟第一次发帖,很多地方不懂,请各位帮忙看看,谢谢。

  • 点赞
  • 回答
  • 收藏
  • 复制链接分享

2条回答

为你推荐