C++如何从存储Base类指针的vector中获取派生类A的实例引用
需求实现方案
这个需求完全可以实现,核心是实现模板化的查询函数配合运行时类型检查完成类型转换。
实现思路
- 首先要让查询函数能访问存储
Base指针的容器,演示中我们将容器设为全局变量,生产环境建议封装到专门的对象管理类中 - 查询函数设计为模板函数,由调用方显式指定要查询的
A类的模板参数类型,编译期确定返回的引用类型 - 函数内部先按名称匹配找到对应指针,再用
dynamic_cast做运行时类型检查,确认类型匹配后返回引用,不匹配或找不到名称时抛出异常做错误处理
完整可运行代码
#include <iostream> #include <string> #include <array> #include <vector> #include <stdexcept> class Base { public: Base(std::string name):name_(name){} virtual ~Base(){} virtual void write()=0; const std::string& name() const { return name_; } private: std::string name_; }; template< typename T> class A : public Base { public: A(std::string name):Base(name),name2_(name + "test"){} ~A(){} void write(); std::string name2_; }; template< typename T> void A<T>::write() { std::cout << name2_ << std::endl; } // 全局存储容器,演示用 std::vector<Base*> dataBase; // 模板查询函数 template<typename T> A<T>& lookup(const std::string& name) { for (auto ptr : dataBase) { if (ptr->name() == name) { A<T>* cast_ptr = dynamic_cast<A<T>*>(ptr); if (cast_ptr != nullptr) { return *cast_ptr; } throw std::runtime_error("Type mismatch for object: " + name); } } throw std::runtime_error("Object not found: " + name); } int main() { A<int> one("one"); A<double> two("two"); A<std::array<double,4>> three("three"); dataBase.push_back(&one); dataBase.push_back(&two); dataBase.push_back(&three); for(auto i : dataBase) { i->write(); } // 调用时显式指定模板参数int A<int>& getOne = lookup<int>("one"); getOne.name2_ = "worked"; for(auto i : dataBase) { i->write(); } return 0; }
运行输出
onetest twotest threetest worked twotest threetest
注意事项
- 必须显式指定模板参数:返回的
A<T>类型是编译期确定的,所以调用时必须通过lookup<T>("name")的方式指定T的类型 - 类型安全:
dynamic_cast会在运行时检查匹配到的对象实际类型是否和指定的A<T>一致,如果不一致会返回空指针,示例中用异常处理错误,你可以根据需求调整处理逻辑 - 生产环境优化:不要用全局变量存容器,可以把容器和查询函数封装到单例的注册表类中,同时做好对象生命周期管理,避免出现悬垂指针
内容的提问来源于stack exchange,提问作者user8458838
相关产品推荐
相关产品推荐

