代码之家  ›  专栏  ›  技术社区  ›  Adam Dohnal

C++与Mixins多态性

  •  4
  • Adam Dohnal  · 技术社区  · 6 年前

    我正在尝试将mixin模式适合我的问题,我有一个多态性问题,我不知道如何有效地解决它。在尝试重新设计我的程序之前,我想问你一些建议(也许有一些很酷的C++特性,我没有意识到)。

    我想以非常简单和简单的方式呈现它,因此这里的用例可能没有意义。

    我只是一个 Window

    struct WindowCreateInfo {
        std::string title;
        int x, y;
        int width, height;
    };
    
    class Window {
    public:
        Window(const WindowCreateInfo &createInfo) :
                title(createInfo.title),
                x(createInfo.x),
                y(createInfo.y),
                width(createInfo.width),
                height(createInfo.height) {}
    
        const std::string &getTitle() const { return title; }
    
        int getX() const { return x; }
    
        int getY() const { return y; }
    
        int getWidth() const { return width; }
    
        int getHeight() const { return height; }
    
    public:
    protected:
        std::string title;
        int x, y;
        int width, height;
    };
    

    然后我定义了两个混音 Resizable Movable 如下

    template<class Base>
    class Resizable : public Base {
    public:
        Resizable(const WindowCreateInfo &createInfo) : Base(createInfo) {}
    
        void resize(int width, int height) {
            Base::width = width;
            Base::height = height;
        }
    };
    
    template<class Base>
    class Movable : public Base {
    public:
        Movable(const WindowCreateInfo &createInfo) : Base(createInfo) {}
    
        void move(int x, int y) {
            Base::x = x;
            Base::y = y;
        }
    };
    

    接下来,我在一些业务层中处理 窗口

    class WindowManager {
    public:
        static void resize(Resizable<Window> &window, int width, int height) {
            window.resize(width, height);
    
            // any other logic like logging, ...
        }
    
        static void move(Movable<Window> &window, int x, int y) {
            window.move(x, y);
    
            // any other logic like logging, ...
        }
    };
    

    这里明显的问题是,下面的代码无法编译

    using MyWindow = Movable<Resizable<Window>>;
    
    int main() {
        MyWindow window({"Title", 0, 0, 640, 480});
    
        WindowManager::resize(window, 800, 600);
    
        // Non-cost lvalue reference to type Movable<Window> cannot bind
        // to a value of unrelated type Movable<Resizable<Window>>
        WindowManager::move(window, 100, 100);
    };
    

    我知道两者之间有区别 Movable<Window> Movable<Resizable<Window>> 因为后者 可移动的 可以使用 可调整大小的 . 在我的设计中,混音器是独立的,它们的混音顺序无关紧要。我想这种混音的用法很常见。

    在尽可能保持设计的同时,有什么方法可以使这个代码编译吗?

    1 回复  |  直到 6 年前
        1
  •  5
  •   Frank    6 年前

    在尽可能保持设计的同时,有什么方法可以使这个代码编译吗?

    您只需让窗口管理器接受 Resizable<> Movable<> 通过模板化方法:

    class WindowManager {
    public:
        template<typename Base>
        static void resize(Resizable<Base> &window, int width, int height) {
            window.resize(width, height);
    
            // any other logic like logging, ...
        }
    
        template<typename Base>
        static void move(Movable<Base> &window, int x, int y) {
            window.move(x, y);
    
            // any other logic like logging, ...
        }
    };