std::dynamic_pointer_cast转换失败问题

问题背景

struct TestBase
{
	virtual void reset(){
		b = 0;
	}

	int b = 10;
};

struct Test : public TestBase
{
	void reset() override {
		TestBase::reset();
		a = 0;
	}
	int a = 10;
};

template<typename T>
T* Construct_Fun()
{
	int i_size = sizeof(T);
	T* p_test_buffer = (T*)(new uint8_t[sizeof(T)]);
	return p_test_buffer;
}

int main()
{
	std::shared_ptr<Test> p_sh_test(Construct_Fun<Test>());
	p_sh_test->reset(); // 错误,直接使用内存的话,类还没有初始化,只有一片裸内存

	//std::shared_ptr<Test> p_sh_test = std::make_shared<Test>();
	std::shared_ptr<TestBase> p_base = p_sh_test;
	auto ppp = p_base.get();
	auto page = std::dynamic_pointer_cast<Test>(p_base);

	return 0;
}

问题1:

最开始是希望使用一块内存池来管理shared_ptr指向的内容,所以上面有个

        std::shared_ptr<Test> p_sh_test(Construct_Fun<Test>());

的代码,后来发现虽然直接转可以,但是调用函数后出现司机错误

        原因如代码中注释所示,申请了一块内存,但是这块内存是没有构造的,所以续表指针为未初始化状态,因此调用虚函数肯定会报错

问题2

        另外一个问题,把上面的虚函数去掉,将reset设置成非虚函数,然后添加一个虚析构函数(必须是多态转换才能使用dynamic_pointer_cast,否则编译失败),然后调用reset是可以的,但是同样的道理,现在的虚函数指针还是未初始化的状态:

 会发现转换到TestBase后,指针里面只维护了b的值和一个无效的续表指针,所以下面的转换dynamic_pointer_cast会失败

解决:

        如果非要按照上面使用内存池来弄的话,那可以不使用虚函数,然后指针转换的时候,使用std::reinterpret_pointer_cast或者static_pointer_cast来解决

猜你喜欢

转载自blog.csdn.net/bocai1215/article/details/129884470