C++中的向量和多态性

use*_*273 6 c++ oop polymorphism vector

我有一个棘手的情况.它的简化形式是这样的

class Instruction
{
public:
    virtual void execute() {  }
};

class Add: public Instruction
{
private:
    int a;
    int b;
    int c;
public:
    Add(int x, int y, int z) {a=x;b=y;c=z;}
    void execute() { a = b + c;  }
};
Run Code Online (Sandbox Code Playgroud)

然后在一个班级我做一些像......

void some_method()
{
    vector<Instruction> v;
    Instruction* i = new Add(1,2,3)
    v.push_back(*i);
}
Run Code Online (Sandbox Code Playgroud)

而在另一堂课......

void some_other_method()
{
    Instruction ins = v.back();
    ins.execute();
}
Run Code Online (Sandbox Code Playgroud)

他们以某种方式分享这个教学载体.我担心的是我执行"执行"功能的部分.它会起作用吗?它会保留其添​​加类型吗?

Dan*_*zer 10

不,它不会.

vector<Instruction> ins;
Run Code Online (Sandbox Code Playgroud)

存储值,而不是引用.这意味着无论你如何,但那里的那个指令对象,它将在未来的某个时刻被复制.

此外,由于您正在分配new,上面的代码泄漏了该对象.如果你想要做到这一点,你必须这样做

vector<Instruction*> ins
Run Code Online (Sandbox Code Playgroud)

或者,更好的是:

vector< std::reference_wrapper<Instruction> > ins
Run Code Online (Sandbox Code Playgroud)

我喜欢这个博客文章来解释reference_wrapper

此行为称为对象切片.

  • 要非常小心`vector <std :: reference_wrapper <Instruction >>`!您必须绝对确定无论您添加到向量中的任何内容的生命周期都长于向量,并且您添加的内容在某些时候会被删除.更好的是使用`vector <std :: unique_ptr <Instruction >>. (8认同)

And*_*zos 6

因此,您将需要某种指针。一个std::shared_ptr很好的工作:

typedef shared_ptr<Instruction> PInstruction;

vector<PInstruction> v;
v.emplace_back(make_shared<Add>());

PInstruction i = v[0];
Run Code Online (Sandbox Code Playgroud)

请记住,PInstruction是引用计数的,因此PInstruction的副本构造函数将为同一对象创建一个新的“引用”。

如果要复制所引用对象,则必须实现克隆方法:

struct Instruction
{

   virtual PInstruction clone() = 0;
   ...
}

struct Add
{
    PInstruction clone() { return make_shared<Add>(*this); }
    ...
}

PInstruction x = ...;
PInstruction y = x->clone();
Run Code Online (Sandbox Code Playgroud)

如果性能是您std::unique_ptr无法解决的问题,则由于始终需要移动语义,因此管理起来有些棘手,但它避免了某些原子操作的成本。

您还可以使用原始指针并通过某种内存池体系结构手动管理内存。

潜在的问题是,要拥有多态类型,编译器将不知道子类的大小,因此您不能只拥有基类型的向量,因为它不会具有所需的额外空间。子类。因此,您将需要使用如上所述的按引用传递语义。这会将指向对象的指针存储在向量中,然后根据子类的需要,将对象存储在堆中的不同大小的块中。