Я попытался ответить на это сам, посмотрев несколько вопросов в 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)
Заранее спасибо за помощь!