C++多态问题:如何用同一函数接收不同子类的vector参数
问题解决:接收不同子类vector的函数实现
首先明确原写法的问题:
- C++标准容器(比如
vector)不能存储引用类型,因为引用不满足容器元素的可赋值、可默认构造等要求,vector<Base&>本身就是非法写法。 - 即使换成指针,
vector<Sub1>和vector<Base*>是完全独立的模板实例,不存在继承或隐式转换关系,无法直接传递给接收vector<Base*>的函数。
下面是几种可行的实现方案:
方案1:模板函数(推荐)
直接定义模板函数,接受任意继承自Base的子类的vector,编译时自动推导类型:
#include <vector> #include <type_traits> // 基类和子类定义不变 class Base { public: int a, b, c; virtual void unreal() = 0; }; class Sub1: public Base { public: virtual void unreal() {} }; class Sub2: public Base { public: virtual void unreal() {} }; template <typename Derived> void Function(const std::vector<Derived>& v) { // 编译期检查:确保Derived是Base的子类 static_assert(std::is_base_of_v<Base, Derived>, "元素类型必须继承自Base"); for (const auto& elem : v) { elem.unreal(); // 多态调用生效 // 可直接访问Base的成员,比如elem.a } } // 调用示例 int main() { std::vector<Sub1> v1; std::vector<Sub2> v2; Function(v1); Function(v2); return 0; }
这种方式无需修改现有容器结构,代码简洁,且编译时就能保证类型合法性,是最直接的解决方案。
方案2:统一使用基类指针容器
如果需要在函数中统一处理不同子类的混合容器,可以让调用方传递std::vector<Base*>或std::vector<std::unique_ptr<Base>>:
#include <vector> #include <memory> void Function(const std::vector<Base*>& v) { for (Base* ptr : v) { ptr->unreal(); // 多态调用 // 访问成员:ptr->a } } // 调用示例 int main() { std::vector<std::unique_ptr<Base>> mixed_v; mixed_v.emplace_back(std::make_unique<Sub1>()); mixed_v.emplace_back(std::make_unique<Sub2>()); // 转换为Base*的vector std::vector<Base*> ptr_v; for (auto& uptr : mixed_v) { ptr_v.push_back(uptr.get()); } Function(ptr_v); // 单一子类vector也可转换后传递 std::vector<Sub1> v1; std::vector<Base*> v1_ptr; for (auto& elem : v1) { v1_ptr.push_back(&elem); } Function(v1_ptr); return 0; }
这种方案适合统一管理不同子类对象生命周期的场景,但调用方需要额外做容器转换。
方案3:迭代器范围模板
如果不需要接收整个vector,只需要遍历元素,可以定义接受迭代器范围的模板函数,适配更多容器类型:
#include <vector> #include <type_traits> template <typename Iterator> void Function(Iterator begin, Iterator end) { using Derived = typename std::iterator_traits<Iterator>::value_type; static_assert(std::is_base_of_v<Base, Derived>, "元素类型必须继承自Base"); for (; begin != end; ++begin) { const auto& elem = *begin; elem.unreal(); } } // 调用示例 int main() { std::vector<Sub1> v1; Function(v1.begin(), v1.end()); std::vector<Sub2> v2; Function(v2.begin(), v2.end()); return 0; }
这种方式灵活性更高,除了vector,还能处理list、array等其他容器的元素遍历。
内容的提问来源于stack exchange,提问作者Sơn Nguyễn Hoàng
相关产品推荐
相关产品推荐

