2021-08-31 C++: 虚继承下array newdelete 的内存管理

2021-08-31 C++: 虚继承下array newdelete 的内存管理,第1张

以下实验基于VS2015, win32环境

array new出来的对象,能否用父类指针能否调用子类虚函数?

如果父类大小 * 元素数目 = 子类大小 * 元素数目,就可以,否则不行。

#include "stdafx.h"
#include 

using namespace std;

class A {
public:
	int x{ 10 };
	virtual void PrintVal(int a = 1) { cout << x + a << endl; }
};

class B : public A {
public:
	int y{ 20 };
	virtual void PrintVal(int a = 2) { cout << y + a << endl; }

};


int main() {
	cout << "sizeof(A): " << sizeof(A) << endl;
	cout << "sizeof(B): " << sizeof(B) << endl;
	A *a = new B[10];
	B *b = static_cast<B *>(a);
	b[2].y = 100;
	cout << "address of b[2]: " << &b[2] << endl;
	cout << "address of a[3]: " << &a[3] << endl;
	a[3].PrintVal();
	a[6].PrintVal();
	// 
	delete[] a;
	system("pause");
	return 0;

}

类A的每个元素大小,如 a[n]:(共8 Byte)

  • _vptr(4 Byte)
  • int x(4 Byte)

类B的每个元素大小,如 b[n]: (共12Byte)

  • 类A{ _vptr + int x)(8 Byte)
  • int y(4 Byte)

在算数组偏移量的时候,按指针类型的size算,如:
a[n]的地址为:sizeof(A) * n
b[m]的地址为:sizeof(B) * m

所以取8与12的最小公倍数24时,分别对应a[3]与b[2]的地址,此时他俩的内存是对齐的,可以调用相应的虚函数,为了验证a[3].func() 确实传入的是b[2]对象的内存地址,我把b[2]成员变量y改为100,其他默认为20,可以看到,a[3]输出的值确实变为100+1,而对于没有改动的a[6],输出值为20+1。
另外,重写函数似乎只重写函数体,仍用的是A类虚函数的默认参数,a = 1。不过有一点还不是很清楚,对象指针this传入B类重写的虚函数是B * 类型的吗?由于可以调用B类的成员函数,应该是这样,但如果是A类的函数,this指针会自动转型为A * 类型吗?

当两者偏移量不匹配时,如: a[7] = 7 * 8 = 56 = 48 + 8 = b[4] + 8,访问到b[4].y 的地址,不是b[4]的地址,会报错。

array delete 父类指针可以正常运行吗?

delete[] a 时会产生和上面一样的问题,因为他只按sizeof(A)的偏移量进行析构,访问到的不是b[n]的地址而是a[n]的地址,理论上是这样,但试验下来,VS的编译器做了优化,不会报错。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/756148.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-30
下一篇 2022-04-30

发表评论

登录后才能评论

评论列表(0条)

保存