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
此行为称为对象切片.
因此,您将需要某种指针。一个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无法解决的问题,则由于始终需要移动语义,因此管理起来有些棘手,但它避免了某些原子操作的成本。
您还可以使用原始指针并通过某种内存池体系结构手动管理内存。
潜在的问题是,要拥有多态类型,编译器将不知道子类的大小,因此您不能只拥有基类型的向量,因为它不会具有所需的额外空间。子类。因此,您将需要使用如上所述的按引用传递语义。这会将指向对象的指针存储在向量中,然后根据子类的需要,将对象存储在堆中的不同大小的块中。