我试图通过在StackOverflow上查找几个问题来回答这个问题。尽管我认为我理解正确,但无法解决。这给我留下了唯一明显的观察:我还是不明白。

我在这篇文章的底部总结了问题,两者之间的一切都是我收集的信息以及此问题的上下文。

因此,我知道,当您具有基类和派生类时,应该在基类中将解构函数标记为虚拟。允许多态。

但是,我似乎无法编译我的代码,或者当它编译时,它没有链接到“未定义的引用”。我一直在来回改变,但是我似乎从未摆脱过这个周期。

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

#ifndef GUIELEMENT_H_
#define GUIELEMENT_H_

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

#endif /* GUIELEMENT_H_ */


我有几个扩展的对象。一个简单的关系是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_ */


这段代码不链接,给我:


  未定义对`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;
};


最后是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_ */


这使我想到以下问题:


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


在此先感谢您的帮助!

最佳答案

在从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;


要么:

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

08-08 00:16