我有一个棘手的情况。 它的简化形式是这样的
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; }
};
然后在一类我做这样的事情?
void some_method()
{
vector<Instruction> v;
Instruction* i = new Add(1,2,3)
v.push_back(*i);
}
而在另一个类...
void some_other_method()
{
Instruction ins = v.back();
ins.execute();
}
和他们莫名其妙地分享这个指令矢量。 我担心的是我做的“执行”功能的一部分。 它是否行得通呢? 它将保留其添加类型?
不,不会。
vector<Instruction> ins;
卖场值,而不是引用。 这意味着,不管你怎么但是在那里,教学对象,它会在未来的某个时候被复制。
此外,由于你和分配new
,上面的代码泄漏该对象。 如果你想正确地做到这一点,你就必须做
vector<Instruction*> ins
或者,更好的是:
vector< std::reference_wrapper<Instruction> > ins
我喜欢这个博客帖子解释reference_wrapper
这种行为被称为对象切片。
所以,你需要某种形式的指针。 一个std::shared_ptr
效果很好:
typedef shared_ptr<Instruction> PInstruction;
vector<PInstruction> v;
v.emplace_back(make_shared<Add>());
PInstruction i = v[0];
请记住,PInstruction是引用计数,使PInstruction的拷贝构造函数将创建一个新的“参考”同一个对象。
如果你想引用对象的副本,你将不得不实现clone方法:
struct Instruction
{
virtual PInstruction clone() = 0;
...
}
struct Add
{
PInstruction clone() { return make_shared<Add>(*this); }
...
}
PInstruction x = ...;
PInstruction y = x->clone();
如果性能是比你可以看一个问题std::unique_ptr
,这是有点麻烦,以管理为移动语义总是必需的,但它避免了一些原子操作的成本。
你也可以使用原始指针,并用某种内存池架构的手工管理的内存。
根本的问题是,有一个多态型的编译器不知道子类有多大将是,所以你不能只是有基本类型的载体,因为它不会有被需要的额外空间子类。 出于这个原因,你需要使用通-by-reference语义如上所述。 这个存储的指针到载体中的对象,然后存储关于这取决于该子类中,需要不同尺寸的块的堆的对象。
不,这是行不通的; 你是“切片”的Add
对象,只有将其Instruction
部分入阵。 我会建议你做基类的抽象(例如,通过使execute
纯虚),使切片给出了一个编译错误,而不是意外的行为。
要获得多态行为,载体需要包含指针的基类。
然后,您就需要小心你如何管理对象本身,因为他们不再包含于载体。 智能指针可以是用于这个有用的; 因为你很可能会被动态分配这些对象,你也应该给基类的虚析构函数,以确保你能正确地将其删除。
您可能需要做两件事,A:改变“V”,以“矢量”,B类型:与“删除”操作员管理你的记忆。 要回答你的问题,用这种方法,是的,但你只能够访问来自“指令”的界面,如果你知道的东西“说明”指针指向我的类型,如果你需要会建议使用的dynamic_cast访问,比如说,从“添加”的接口。