我试图通过在StackOverflow上查找几个问题来自己回答这个问题。虽然我认为我理解正确,但我无法解决这个问题。其中,给我留下了唯一明显的观察结果:我仍然没有得到它。
我在这篇文章的底部总结了一些问题,其间的一切都是我收集的信息和这个问题的背景。
所以,我知道当你有一个基类和一个派生类时,你的解构函数应该在基类中标记为虚拟。允许多态。
但是,我似乎无法将我的代码编译,或者当它编译时,它没有链接到'undefined references'。我一直在来回变换,但我似乎永远不会离开这个循环。
基本上我有一个interace,定义如下:
#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-&GT; GuiShape-&GT; 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_ */
这引出了以下问题:
提前感谢您的帮助!
答案 0 :(得分:5)
使用虚拟解构器的最佳方法是什么,其中对象来自A-> B-> C?
将基础(或所有)析构函数标记为虚拟。
C应该只是具体虚拟吗?如果是这样,您如何释放仅在B中定义和处理的资源? (A = GuiElement,B = GuiShape,C = GuiButton)
不确定“具体虚拟”是什么意思,但是需要销毁的成员的类应该在它自己的析构函数中销毁它们。没有例外。当调用~C
时,它会破坏它的自己的内容,然后~B
将自动调用 。虚拟只是确保首先调用~C
。
为什么我会直接实现A-&gt; B获得'未定义的引用'? (GuiElement-&GT; 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() {};
答案 1 :(得分:2)
我认为在GuiWindow课程中有一个实现就足够了吗?这是对的吗?
没有。如果在类中声明了虚函数(不是纯虚函数,作为GuiElement的析构函数),则必须定义它。
析构函数更进一步:它们必须始终实现,即使它是纯虚[1]。如果你还没有声明它,编译器会为你创建一个(隐式非虚拟,但如果它会覆盖虚拟析构函数则为虚拟)。在C ++ 11中,您可以将其标记为“默认”(这意味着“编译器,为我实现”)和“删除”,这意味着“程序可能永远不会,隐式或显式地破坏此类对象”。 / p>
- 使用虚拟解构器的最佳方法是什么,其中对象来自A-> B- C?
醇>
您通常希望将最顶层的析构函数设为虚拟,这意味着层次结构中的所有析构函数都是虚拟的。
如果是这样,你如何释放仅在B中定义和处理的资源? (A = GuiElement,B = GuiShape,C = GuiButton)
~B()
,自然。
[1]:
12.4 / 7:析构函数可以声明为虚拟(10.3)或纯虚拟(10.4);如果该类的任何对象或任何 派生类是在程序中创建的,应该定义析构函数。如果一个类有一个基类 虚析构函数,它的析构函数(无论是用户还是隐式声明)都是虚拟的。