接口 - >抽象 - >具体类设计中的虚拟解构器

Ste*_*iks 0 c++ virtual inheritance

我试着通过在StackOverflow上查找几个问题来自己回答这个问题.虽然我认为我理解正确,但我无法解决这个问题.其中,给我留下了唯一明显的观察结果:我仍然没有得到它.

我已经在这篇文章的底部总结了一些问题,其间的一切都是我收集的信息和这个问题的背景.

所以,我知道当你有一个基类和一个派生类时,你的解构函数应该在基类中标记为虚拟.允许多态.

但是,我似乎无法让我的代码进行编译,或者当它编译时,它不会因为"未定义的引用"而链接.我一直在来回变换,但我似乎永远不会摆脱这个循环.

基本上我有一个interace,定义如下:

#ifndef GUIELEMENT_H_
#define GUIELEMENT_H_

class GuiElement {
    public:
    virtual ~GuiElement();
    virtual void draw() = 0;
};

#endif /* GUIELEMENT_H_ */
Run Code Online (Sandbox Code Playgroud)

我有几个从此延伸的对象.一个简单的关系是GuiWindow(直接来自GuiElement):

#ifndef CGUIWINDOW_H_
#define CGUIWINDOW_H_

#include <assert.h>
#include <cstddef>

#include "../GuiElement.h"
#include "../GuiInteractionDelegate.h"

class GuiWindow : public GuiElement {

    public:
        GuiWindow(GuiInteractionDelegate * guiInteractionDelegate) {
            assert(guiInteractionDelegate);
            interactionDelegate = guiInteractionDelegate;
        }

        ~GuiWindow() {
            //delete interactionDelegate;
        }

        // called each frame, delegates its behavior to the given concrete cGuiWindowDelegate class.
        void interact() {
            interactionDelegate->interact(this);
        }

    private:
        GuiInteractionDelegate * interactionDelegate;

};

#endif /* CGUIWINDOW_H_ */
Run Code Online (Sandbox Code Playgroud)

这段代码没有链接,给我:

未定义引用`GuiElement :: ~GuiElement()'

我认为在GuiWindow课程中实现它已经足够了吗?那是对的吗?

接下来我真正烦恼的是,我还有一个派生自GuiElement的抽象类,以及基于此的具体实现.基本上给予:GuiElement-> GuiShape-> GuiButton

这是GuiShape的标题:

#ifndef GUISHAPE_H_
#define GUISHAPE_H_

#include "../GuiElement.h"
#include "../../gameobjects/Rectangle.h"

class GuiShape : public GuiElement {

    public:
        GuiShape(Rectangle * rect);
        GuiShape(int x, int y, int width, int height);

        ~GuiShape();

        void draw();

        void setX(int value) { rectangle->setStartX(value);     }
        void setY(int value) { rectangle->setStartY(value);     }

        Rectangle * getRectangle() { return rectangle; }

        bool isMouseOverShape();

        void setColors(int darkBorder, int lightBorder, int inner);

        int getDarkBorderColor() { return darkBorderColor; }
        int getLightBorderColor() { return lightBorderColor; }
        int getInnerColor() { return innerColor; }

    protected:
        Rectangle * rectangle;

    private:
        bool rectangleOwner;
        int darkBorderColor;
        int lightBorderColor;
        int innerColor;
};
Run Code Online (Sandbox Code Playgroud)

最后GuiButton:

#ifndef CGUIBUTTON_H_
#define CGUIBUTTON_H_

#include <sstream>
#include <string>

#include "allegro.h"

#include "../../gameobjects/Rectangle.h"
#include "GuiShape.h"

class GuiButton : public GuiShape {

    public:
        GuiButton(Rectangle * rect, std::string theLabel);
        GuiButton(int x, int y, int width, int height, std::string theLabel);
        ~GuiButton();

        void draw();

        std::string * getLabel() {
            return label;
        }

        BITMAP * getBitmap() { return bitmap; }
        void setBitmap(BITMAP * value) { bitmap = value; }
        void setHasBorders(bool value) { hasBorders = value; }
        void setPressed(bool value) { pressed = value; }

        bool shouldDrawPressedWhenMouseHovers() { return drawPressedWhenMouseHovers; }
        bool shouldDrawBorders() { return hasBorders; }
        void setDrawPressedWhenMouseHovers(bool value) { drawPressedWhenMouseHovers = value; }
        bool isPressed() { return pressed; }

    private:
        std::string * label;
        bool drawPressedWhenMouseHovers;
        bool hasBorders;
        bool pressed;
        BITMAP * bitmap;

        void drawBackground();
        void drawLighterBorder();
        void drawDarkerBorder();
        void drawButtonUnpressed();
        void drawButtonPressed();
};

#endif /* CGUIBUTTON_H_ */
Run Code Online (Sandbox Code Playgroud)

这引出了以下问题:

  • 使用虚拟解构器的最佳方法是什么,其中对象派生自A-> B-> C?
  • C应该只是具体的虚拟吗?如果是这样,您如何释放仅在B中定义和处理的资源?(A = GuiElement,B = GuiShape,C = GuiButton)
  • 为什么我会直接实现A-> B获得"未定义的引用"?(GuiElement-> GuiWindow)

在此先感谢您的帮助!

Moo*_*uck 5

使用虚拟解构器的最佳方法是什么,其中对象派生自A-> B-> C?

将基础(或所有)析构函数标记为虚拟.

C应该只是具体的虚拟吗?如果是这样,您如何释放仅在B中定义和处理的资源?(A = GuiElement,B = GuiShape,C = GuiButton)

不确定你的意思是"具体的虚拟",但是一个需要销毁的成员的类应该在它自己的析构函数中销毁它们.没有例外.当~C被调用时,它会破坏它自己的东西,然后自动~B被调用.虚拟只是确保首先调用.~C

为什么我会直接实现A-> B获得"未定义的引用"?(GuiElement-> GuiWindow)

virtual ~GuiElement();告诉编译器该类有一个稍后定义的析构函数.你想要:

// There is no definition, cannot make a local "GuiElement" variable
// They can only make local "GuiButton" or other derived.
// You can still have pointers to a GuiElement.
// This is called "pure virtual"
virtual ~GuiElement() = 0; 
Run Code Online (Sandbox Code Playgroud)

要么:

// There is a definition, someone can make a local "GuiElement" variable
virtual ~GuiElement()  {};
Run Code Online (Sandbox Code Playgroud)