派生对象/智能指针的容器

Container of derived objects / smart pointers

本文关键字:指针 智能 对象 派生      更新时间:2023-10-16

假设我有:

class Base {...};
class Derived1 : public Base {...};
class Derived2 : public Base {...};
class Derived3 : public Base {...};
class Store {
public:
    void Add(const Base&);    //Adds mix of Derived1/2/3
private:
    vector<const Base*> vec;    
    vector<shared_ptr<const Base> > vec_smart;
};
//------------------------------------------------------
void Store::Add(const Base& b){
    vec.push_back(&b);    //got sliced
}

当使用指向Base的指针向量时,它被切片了。我想我必须使用智能指针,但我无法让它发挥作用。

我试过类似的东西:

auto tmp = make_shared<const Base> (b);
vec_smart.push_back(shared_ptr<const Base>(b));

但它还是被切开了。我做错了什么?

编辑:我有<lt;基类中调用派生类中的虚拟打印的运算符。

ostream & operator <<(ostream & os, const Base & x) {
    x.print(os);
    return os;
}
void Base::print(ostream& os) const {
   os << "Base";
}
void Derived1::print(ostream& os) const {
   os << "Derived1";
}

当我呼叫时

cout << b;

In Store::Add它输出良好,但当我在向量存储后迭代时,我得到的只是"基本"

ostream & operator <<(ostream & os, const Store & x) {
    for (auto it = x.vec.begin(); it != x.vec.end(); ++it) {
        os << *(*it) << endl;
    }
    return os;
}

这是一个糟糕的设计吗?

我猜您没有将Base中的相关方法声明为virtual。试试这个:

struct Base
{
  virtual void print(std::ostream& os) const { os << "Base"; }
  virtual ~Base() {}
};
struct Derived1 : Base
{
  void print(std::ostream& os) const { os << "Derived1"; }
};

等等。注意,我在这里只使用了struct,以节省我键入public的次数。

下面是一个工作示例:

#include <vector>
int main()
{
  Base b;
  Derived1 d;
  std::vector<const Base*> v{&b, &d};
  for (auto it = v.cbegin(); it != v.cend(); ++it)
  {
    std::cout << *(*it) << std::endl;
  }
}

输出:

Base
Derived1

您可以在此处看到它的作用。

编辑您的代码有未定义的行为,因为您正在存储指向临时性的指针:

Store a("aaaaaaa");
a.Add(Derived("abc", 5));
a.Add(Derived("def", 6));

此版本按预期工作:

Store a("aaaaaaa");
Derived d0("abc", 5);
Derived d1("def", 6);
a.Add(d0);
a.Add(d1);

编辑2:来自您的评论:

比方说我被迫使用a.Add(派生的("abc",5));在我的实现中,我可以用它做什么?

您可以将Add作为模板:

template <typename T>
void Add(const T& elem)
{
  vec.push_back(new T(elem));
}

template <typename T>
void Add(const T& elem)
{
  vec_smart.push_back(std::make_shared(elem));
}