我实施的virtual clone()
方法可以完全相同,除了"实际"返回的对象的类型,我意识到会有很多重复。例如,这是我想要避免的明显解决方案:
AbstractVehicle* ConcreteCar::clone() const
{
auto c = new ConcreteCar;
c->setSomething(this->getSomething());
return c;
}
AbstractVehicle* ConcreteJet::clone() const
{
auto j = new ConcreteJet;
j->setSomething(this->getSomething());
return j;
}
这就是我想要的:
AbstractVehicle* AbstractVehicle::clone() const
{
auto v = new this->ACTUAL_CLASS;
v->setSomething(this->getSomething());
return v;
}
有没有直接的方法来做到这一点?如果没有,我很想知道为什么会出现这种情况,因为天真地看起来实施起来并不像动态调度那样具有挑战性。
答案 0 :(得分:2)
没有。 operator new
要求在编译时指定要创建的对象的类型。你要求的是要求在编译时创建对象的类型是未知的,并在运行时计算出(或以其他方式获得)。
答案 1 :(得分:1)
没有直接的方法可以做到这一点。但是,(我可能因此而被绞死)您可以通过使用预处理器定义来避免编写clone
函数的多个定义,如下所示:
#define DEFINE_VEHICLE_CLONE_MEMFUN(Vehicle) \
AbstractVehicle* Vehicle::clone() const { \
auto v = new Vehicle; \
v->setSomething(this->getSomething()); \
return v; \
}
然后在代码中将成员函数定义为:
DEFINE_VEHICLE_CLONE_MEMFUN(ConcreteCar)
DEFINE_VEHICLE_CLONE_MEMFUN(ConcreteJet)
答案 2 :(得分:1)
根据您定义的setSomething / getSomething函数的小时数,您可以保留单个克隆,并且只需覆盖“创建我”类型函数。例如:
AbstractVehicle* ConcreteCar::MakeNew() { // virtual method
return new ConcreteCar();
}
这将从基类clone中调用:
AbstractVehicle* AbstractVehicle::Clone() {
auto j = MakeNew();
j->setSomething(this->getSomething());
return j;
}
答案 3 :(得分:0)
这可能不是你要求的;但这可能会实现你所追求的目标。我这里有一个抽象基类,有三个定义的派生类。我在类中没有一个虚拟类型的克隆方法,但我所拥有的是一个模板函数,可以为你工作。
var increment = $('#vehiclePhotoPreview' + photoID).width() + 10; //10 would be the space between each image
$('.vehicleDetailExpandedPhotoReel').scrollLeft(photoID * increment); //assuming that photoID is always sequential
另一个提醒是这个;模板函数和类通过new和delete运算符清理堆上的内存。因此需要谨慎使用这种方法或方法。如果想要实现类似的方法,但不必担心清理动态内存,那么应该在函数模板中使用智能指针。