我正在为我拥有的所有GUI对象创建Display list
,如下所示:
glNewList(displayList, GL_COMPILE);
obj->draw();
glEndList();
但是当我尝试编译它时,我收到一个错误:
R6025 - pure virtual call
draw()
方法是纯虚拟的。但我想知道,为什么我不能将虚函数放在Display list
内?
编辑:
这是GUIObject类:
class GUIObject
{
protected:
int m_id;
int m_parentId;
int m_width;
int m_height;
Point m_position;
Point m_drawPosition;
bool m_bEnabled;
bool m_bVisible;
GLuint m_displayListId; // Id in display lists array in TGUIManager
virtual void onDrawStart() = 0;
virtual void onDrawFinish() = 0;
public:
virtual bool draw() = 0;
void setDisplayListId(GLuint id);
GLuint getDisplayListId();
virtual int getWidth() const;
virtual int getHeight() const;
virtual bool pointInObject(const TPoint& point);
GUIObject();
virtual ~GUIObject();
};
GUIObject::GUIObject() :
m_position(Point(0,0)),
m_width(0),
m_height(0),
{
m_drawPosition = m_position;
GUIManager::Instance().addObject(this);
}
GUIObject::~GUIObject()
{
}
这是Button
类,它派生自Component
,源自GUIObject
:
class Button : public Component, public Clickable
{
private:
std::string m_text;
TBackground* m_pBackground;
public:
void setText(std::string text);
void setBackground(Background* pBg);
Background* getBackground() const;
void setBackgroundOnClick(Background* pBg);
Background* getBackgroundOnClick() const;
bool draw();
int getFontSize() const;
std::string getText() const;
Button& operator=(const Button & button);
// From Clickable
bool wasClicked(const Point& clickPos);
Button();
~Button();
};
bool Button::draw()
{
onDrawStart(); // This needs to be called in each object
if(!isClicked() && m_pBackground != nullptr)
m_pBackground->draw(m_drawPosition, m_width, m_height);
else if(m_pBackgroundOnClick != nullptr)
m_pBackgroundOnClick->draw(m_drawPosition, m_width, m_height);
FontManager::Instance().renderLineOfText(font, lineLength, pos, textToRender);
onDrawFinish(); // This needs to be called in each object
return true;
}
Button::Button() :
TComponent(Point(0,0)),
m_pBackground(nullptr),
m_pBackgroundOnClick(nullptr),
m_text("")
{
}
Button::~Button()
{
if(m_pBackground != nullptr)
{
delete m_pBackground;
m_pBackground = nullptr;
}
}
Button& Button::operator=(const Button & button)
{
m_position = Point(button.getPos());
m_pBackground = new Background()
return *this;
}
好的,我想我已经包含了所有必需的代码部分。
绘图内容位于Background
的{{1}}方法内。
名为draw()
的对象是obj
构造函数中addObject()
方法中作为参数传递的对象:
GUIObject
答案 0 :(得分:2)
好的,所以我觉得这是一个非常愚蠢的错误。正如我在编辑中对我提出的问题所解释的那样,obj
对象是在方法addObject()
中作为参数传递的对象,它在GUIObject
的构造函数中被调用,这意味着{{ 1}}的对象本身尚未创建。编译器没有抱怨,因为Button
类已声明GUIObject
方法,但仅在运行时找不到此方法的定义。
但无论如何,感谢大家告诉我,调用纯虚方法在显示列表中完全没问题。这帮我找到了解决方案。
答案 1 :(得分:1)
我目前唯一可能的做法是Component
未定义virtual void onDrawStart() = 0
或virtual void onDrawFinish() = 0
。但是,当您实例化Button
时,您应该已经收到错误。
您不会在任何地方声明m_pBackgroundOnClick
。它应该是Button
的成员吗?
答案 2 :(得分:-1)
但我想知道,为什么我不能将虚拟功能放在显示列表中?
该问题与OpenGL显示列表无关。 Heck OpenGL显示列表在运行时编译,甚至不与编译单元级别的函数交互。
我的印象是您可能认为OpenGL显示列表会“记录”其中的 所有内容 。不是这种情况。 OpenGL显示仅列出记录OpenGL API调用的子集。
发生的是,obj
是从基类派生的类的实例,其中draw
已被声明为纯虚拟。 E.g。
class A {
virtual void draw() = 0; // draw is a pure virtual function
};
派生类
class B : public A {
// does not implement draw()
};
现在,如果你的程序中有一些指向A的指针,即
A *pA;
然后编译器当然会允许在这个指针上调用draw
pA->draw();
在有效推定下,pA实际上可能指向B
B b;
A *pA = &b;
但是b没有实现绘制,因此呼叫转到了必杀技。