如何在C++中创建Interface_A&类型的向量?
问题与代码
以下是代码:
#include <iostream> class Interface_A { public:virtual bool dothething () = 0; }; class Inherit_B:public Interface_A { bool dothething () { std::cout << "Doing the thing in B\n"; return true; } }; class Inherit_C:public Interface_A { bool dothething () { std::cout << "Doing the thing in C\n"; return true; } }; /**This works */ Interface_A& makeBC () { #ifdef make_B return *(new Inherit_B ()); #elif make_C return *(new Inherit_C()); #endif } /**This doesn't work Interface_A makeC () { #ifdef make_B return ((Interface_A) (new Inherit_B ())); #elif make_C return ((Interface_A) (new Inherit_C ())); #endif } */ int main () { Interface_A& obj = makeBC (); obj.dothething(); // ultimate goal is to make a vector of type <Interface_A&> return 0; }
核心需求:
- 无法创建
vector<Interface_A&>类型容器,因为C++标准容器不支持存储引用(引用不可默认构造、不可重新绑定,不符合容器元素要求) - 不能直接创建
vector<Interface_A>,因为Interface_A是抽象类,无法实例化 - 不能用具体派生类(如
Inherit_B)作为返回/容器类型,活跃类由编译时宏定义确定 - 性能要求极高,不能使用智能指针
解决方案
1. 使用原始指针容器(最优性能选择)
标准容器可以存储原始指针,这是性能开销最小的方案,完全符合性能要求。由于编译时已确定活跃类,容器内所有指针都会指向同一种派生类实例,无额外运行时开销。
修改后代码示例:
#include <iostream> #include <vector> class Interface_A { public: virtual bool dothething() = 0; virtual ~Interface_A() = default; // 必须添加虚析构函数,避免内存泄漏 }; class Inherit_B : public Interface_A { bool dothething() override { std::cout << "Doing the thing in B\n"; return true; } }; class Inherit_C : public Interface_A { bool dothething() override { std::cout << "Doing the thing in C\n"; return true; } }; Interface_A* makeBC() // 修改为返回指针,逻辑更直观 { #ifdef make_B return new Inherit_B(); #elif make_C return new Inherit_C(); #endif } int main() { std::vector<Interface_A*> obj_vec; // 添加实例到容器 obj_vec.push_back(makeBC()); obj_vec.push_back(makeBC()); // 调用方法 for (auto* obj : obj_vec) { obj->dothething(); } // 手动释放内存,避免泄漏 for (auto* obj : obj_vec) { delete obj; } obj_vec.clear(); return 0; }
注意要点:
- 必须给
Interface_A添加虚析构函数,否则删除派生类指针时会调用基类析构函数,导致内存泄漏 - 原始指针需要手动管理内存,确保不再使用时释放
2. 利用编译时类型别名(无内存管理负担)
由于活跃类由编译时宏定义确定,可以用类型别名绑定到当前活跃的派生类,容器直接存储派生类对象,既保证性能,又避免手动内存管理:
#include <iostream> #include <vector> class Interface_A { public: virtual bool dothething() = 0; }; class Inherit_B : public Interface_A { bool dothething() override { std::cout << "Doing the thing in B\n"; return true; } }; class Inherit_C : public Interface_A { bool dothething() override { std::cout << "Doing the thing in C\n"; return true; } }; // 编译时确定活跃类型 #ifdef make_B using ActiveType = Inherit_B; #elif make_C using ActiveType = Inherit_C; #endif // 返回活跃类型的引用 ActiveType& makeBC() { // 若无需动态分配,可返回局部静态对象避免内存管理 static ActiveType instance; return instance; } int main() { std::vector<ActiveType> obj_vec; // 若需要基类接口,也可存储引用包装器:std::vector<std::reference_wrapper<Interface_A>> obj_vec; // 直接构造实例添加到容器 obj_vec.emplace_back(); obj_vec.emplace_back(); // 通过基类接口调用方法 for (Interface_A& obj : obj_vec) { obj.dothething(); } return 0; }
该方案优势:
- 无指针开销,性能最优
- 无需手动管理内存(容器自动管理对象生命周期)
- 编译时确定类型,无运行时多态开销(直接调用派生类方法时)
为什么vector<Interface_A&>不可行?
C++标准容器的元素必须满足可默认构造、可复制/移动赋值的要求,而引用不具备这些特性:
- 引用必须在声明时初始化,无法默认构造
- 引用一旦绑定对象,就不能重新绑定到其他对象,无法执行赋值操作
因此标准库不支持直接存储引用的容器,只能用指针或std::reference_wrapper(但后者本质是指针包装,性能略低于原始指针)
内容的提问来源于stack exchange,提问作者doa4321
相关产品推荐
相关产品推荐

