MFC中一个类的成员变量值自动被篡改:多重继承带来的问题

今天发现一个奇葩的bug:

一个类中的某个成员变量的值,在初始化的时候已经赋值为 true 在这里插入代码片了,可是在使用这个类的时候,发现它的值自动变为了 false

cpp 复制代码
class SipPhoneController : public IHardwareController, public CWnd
{
	...

	public:
	bool ready;

	...
}

我在所有涉及到改变量赋值的地方都打上了断点,打算跟踪看看什么地方导致了重新赋值,可是结果却是没有任何断点被触发。

我把 ready 加了监视,单步调试进去,之前一直是 true,但只要已进入SipPhoneController 的方法,值立马变成了 false

担心 SipPhoneController 对象被意外销毁后重建,导致 ready 被重置,又在 SipPhoneController 的构造和析构函数中打上断点,可依旧没有被触发。

还以为又是vs抽风,把项目清理,重新编译,重启vs都无效,,,

直到抱着试试的态度把 SipPhoneController 的继承顺序改了一下,如下:

cpp 复制代码
class SipPhoneController : public CWnd, public IHardwareController
{
	...

	public:
	bool ready;

	...
}

结果奇迹般就正常了。

那么继承顺序的不同为什么会出现值变化?

可能原因1:this指针偏移

在MFC框架中,当处理消息时,MFC内部会使用CWnd的this指针。如果CWnd不是第一个基类,那么:

cpp 复制代码
// 当MFC调用消息处理函数时,隐含的this指针是基于CWnd部分的
// 如果CWnd不是第一个基类,this指针需要偏移

CWnd* pWnd = this; // 这里会发生指针偏移

// 在消息处理函数中访问成员变量时,使用的是偏移后的this指针
// 导致访问到错误的内存位置

可能原因2:MFC内部机制

MFC有很多内部实现依赖于CWnd在对象开始位置:

cpp 复制代码
// MFC内部可能有的代码
void SomeMfcInternalFunction(CWnd* pWnd)
{
    // 假设MFC内部直接通过CWnd指针访问某些数据
    // 如果CWnd不在对象开头,就会访问到错误的内存
    SomeData* pData = reinterpret_cast<SomeData*>(pWnd);
    // 这里如果CWnd不在开头,pData就指向了错误的位置
}

可能原因3:虚函数表问题

如果IHardwareController有虚函数,而CWnd也有虚函数表,多重继承时的虚函数表布局可能会导致问题。

相关推荐
星马梦缘12 小时前
算法与数据结构
数据结构·c++·算法·动态规划·克鲁斯卡尔·kahn
你的冰西瓜13 小时前
C++中的array容器详解
开发语言·c++·stl
Ccjf酷儿13 小时前
C++语言程序设计 (郑莉)第六章 数组、指针和字符串
开发语言·c++
陌路2013 小时前
C++28 STL容器--array
开发语言·c++
im_AMBER13 小时前
Leetcode 100 在链表中插入最大公约数
数据结构·c++·笔记·学习·算法·leetcode·链表
Z1Jxxx13 小时前
删除字符串2
开发语言·c++·算法
你的冰西瓜13 小时前
C++中的set容器详解
开发语言·c++·stl
苦藤新鸡14 小时前
9.找到字符串中所有字母异位词
数据结构·c++·算法·力扣
令狐掌门14 小时前
C++ io_uring介绍
c++·io_uring
青小莫14 小时前
C++之类和对象(下)
java·开发语言·c++