You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 00:50:23