luike 2017-06-24 05:47 采纳率: 0%
浏览 1472

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

我们知道虚函数表在编译时期被确定,虚表指针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条回答 默认 最新

  • luike 2017-06-24 05:48
    关注

    额,这样看起来好混乱,早知道直接贴图了?CSDN发帖能贴图吗?
    各位大神将就看下,麻烦了

    评论

报告相同问题?

悬赏问题

  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥15 stable diffusion
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘