假设我有以下情况(简化案例):
class Color;
class IColor
{
public:
virtual Color getValue(const float u, const float v) const = 0;
};
class Color : public IColor
{
public:
float r,g,b;
Color(float ar, float ag, float ab) : r(ar), g(ag), b(ab) {}
Color getValue(const float u, const float v) const
{
return Color(r, g, b)
}
}
class Material
{
private:
IColor* _color;
public:
Material();
Material(const Material& m);
}
现在,我有什么办法可以在Material的复制构造函数中对抽象IColor进行深层复制吗?也就是说,我希望复制任何 m._color 的值(颜色、纹理),而不仅仅是指向 IColor 的指针。
您可以在界面中添加一个clone()函数。
您必须自己将该代码添加到材质复制构造函数中。然后编写代码以释放析构函数中分配的 IColor。
您还需要向 IColor 添加虚拟析构函数。
自动进行深层复制的唯一方法是直接存储颜色而不是指向 IColor 的指针。
向颜色添加clone() 方法可能是最好的,但如果您没有该选项,另一个解决方案是使用dynamic_cast 将IColor* 转换为Color*。然后你可以调用 Color 复制构造函数。
如果您有一个为您创建颜色的“类似工厂”的类,您可以为用户实现一个类型擦除的向上转换复制构造函数。在你的情况下,它可能不适用,但当它适用时,我发现它比在实现者上强制执行克隆功能更优雅。
struct IColor {
/* ... */
// One way of using this.
// If you have a "manager" class, then this can be omitted and completely
// hidden from IColor implementers.
std::unique_ptr<IColor> clone() const final {
return cpy_me(this); // upcasts
}
// There are other ways to riff around the idea, but the basics are the same.
private:
friend struct ColorMaker;
IColor() = default;
using cpy_callback_t = std::unique_ptr<IColor> (*)(const IColor*);
cpy_callback_t cpy_me = nullptr;
};
struct ColorMaker {
template <class T>
static std::unique_ptr<IColor> make_color() {
static_assert(std::is_base_of_v<IColor, T>, "bleep bloop, no can do");
std::unique_ptr<IColor> ret = std::make_unique<T>();
// Encoding type T into the callback, type-erasing it.
// IColor implementer only has to implement copy constructor as usual.
ret.cpy_me = [](const IColor* from) -> std::unique_ptr<IColor> {
return std::make_unique<T>(*static_cast<const T*>(from));
};
return ret;
}
}
您可以使用原型设计模式来克隆对象:https://refactoring.guru/design-patterns/prototype。它本质上是在接口中声明一个
clone()
方法并在每个实现中定义它。