17

假设我有以下(简化案例):

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 的指针。

4

5 回答 5

28

看看虚拟构造函数的成语

于 2009-09-28T14:13:18.620 回答
8

您可以在界面中添加一个 clone() 函数。

于 2009-09-28T14:12:14.990 回答
1

您必须自己将该代码添加到 Material 复制构造函数中。然后编写代码以释放析构函数中分配的 IColor。

您还需要向 IColor 添加一个虚拟析构函数。

自动进行深拷贝的唯一方法是直接存储颜色而不是指向 IColor 的指针。

于 2009-09-28T14:12:58.887 回答
0

将 clone() 方法添加到颜色可能是最好的,但如果您没有该选项,另一种解决方案是使用 dynamic_cast 将 IColor* 转换为 Color*。然后您可以调用 Color 复制构造函数。

于 2009-09-28T18:51:37.327 回答
0

如果你有一个为你创建颜色的“类工厂”类,你可以为用户实现一个类型擦除向上转换的复制构造函数。在您的情况下,它可能不适用,但是当它适用时,我发现它比对实施者强制执行克隆功能更优雅。

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;
    }
}
于 2021-02-19T18:17:01.357 回答