C++传入Child指针数组到Parent指针数组参数报错如何解决
问题原因
- 单个
Child*到Parent*的转换合法:公有继承场景下,子类对象包含父类的完整子对象,Child*向上转型为Parent*是C++标准允许的隐式安全转换,编译器会自动调整指针偏移,保证转换后的指针准确指向对象中的Parent子对象部分,不会出现类型安全问题。 Child**到Parent**的转换被禁止:核心是存在明确的类型安全风险,C++标准直接禁止该隐式转换,风险场景如下:
假设存在另一个继承自
Parent的子类OtherChild,如果允许Child**转Parent**传入func,函数内部可以合法执行p[0] = new OtherChild();的赋值操作。此时外部原数组是Child*类型,后续取出c[0]访问Child类独有成员时,实际指向的是OtherChild对象,直接触发未定义行为。
不使用模板的可行解决方案
方案一:调用侧手动构造转换后的Parent*数组(最稳妥,无安全风险)
无需修改原func函数定义,在调用侧将Child*数组的元素逐个转换为Parent*,存入新的Parent*数组后传入即可,代码示例:
int main() { Child *c[10]; Parent* p_arr[10]; for(int i = 0; i < 10; ++i) { p_arr[i] = c[i]; // 单个指针转换合法 } func(p_arr); // 如果func修改了指针指向的对象内容,改动会同步到原Child对象,符合预期 }
方案二:修改函数参数为容器类型
将func的参数改为std::vector<Parent*>类型,调用时把Child*逐个存入vector传入即可,本质和方案一一致,相比原生数组更易用安全:
// 修改后的func定义 void func(std::vector<Parent*> p) { // 原有逻辑无需改动 } int main() { Child *c[10]; std::vector<Parent*> p_vec; p_vec.reserve(10); for(int i = 0; i < 10; ++i) { p_vec.push_back(c[i]); } func(p_vec); }
方案三:显式强制转换(仅推荐完全可控函数逻辑时使用)
如果你100%确定func内部不会修改数组内的指针指向(即不会给p[i]赋值其他Parent子类指针),可以使用显式强制转换绕过编译检查,注意该方式存在潜在安全风险,一旦内部修改数组元素指向就会触发未定义行为:
int main() { Child *c[10]; func(reinterpret_cast<Parent**>(c)); }
内容的提问来源于stack exchange,提问作者BaridunDuskhide
相关产品推荐
相关产品推荐

