2012-10-20 95 views
0

我正在研究一个简单的图形引擎,并且我有Drawable对象,在创建时(在构造函数中),它们应该将自己注册到Renderer(通过将它们插入集合中)。它们还需要进行排序(通过透明度,深度遮罩等),即它们需要通过一些布尔标志进行排序。std :: set的有效比较函数

所以这里是我的设置。

std::set<Drawable *, DrawableComp> drawable_set; 

比较函子:中可绘制

struct DrawableComp : public std::binary_function<const Drawable *, const Drawable *, bool> { 
    bool operator() (const Drawable * lhs, const Drawable * rhs) const 
    { 
     return *lhs < *rhs; 
    } 
}; 

和重载操作<:

bool Drawable::operator<(const Drawable & rhs) const 
{ 
    if (writesDepth() != rhs.writesDepth()) 
     return !writesDepth() < !rhs.writesDepth(); 
    else 
     return getSortNumber() < rhs.getSortNumber(); 
} 

注意,这应该可绘制插入的顺序设置,这样第一次去那个写对象到深度缓冲区,然后是那些不写入深度缓冲区的深度缓冲区。排序号码对每个对象都是唯一的。

问题是,这是行不通的。我在Draw集合的末尾写入深度缓冲区的Drawables。

此外,writeDepth()是虚拟布尔函数。 Drawable只是一个抽象接口。如果我写writeDepth()纯虚拟,我得到运行时错误“纯虚方法调用”。我不清楚为什么会这样,因为我从来没有将Drawable对象设置为集合,而是将其具体实现。

+0

只要您创建'writesDepth()'pure,就会得到_pure虚拟方法called_,这一事实表明至少有一个派生类不会覆盖方法。这可能是导致排序顺序错误的原因(派生类的所有实例将被错误地排序,因为它们的writesDepth()方法不存在,因此会退回到返回错误值的基类方法)。那可能吗? – jogojapan

+0

这不是我想的。我尝试了打印和放置断点。我有两个Drawable实现。 writeDepth()实现和Drawable接口被调用。 –

+1

接口的'writeDepth()'也被调用?然后,无论是从派生类中调用它(是吗?),或者必须至少有一个派生实现不能正确覆盖它。你可以为这两个派生类发布'writeDepth()'的代码吗?也许他们没有被正确覆盖。 – jogojapan

回答

0

好吧,我发现问题了。我正在从Drawable构造函数注册Drawables。我在构造函数中调用这个(registerDrawable刚刚插入到集):

Application::get().getRenderer().registerDrawable(this); 

问题是,这将指向对象类型可绘制,而一些派生类型,所以设置“不知道”类是什么派生它只是调用基本方法writeDepth()。

简单的解决方案是将此调用移至派生构造函数。尽管它在我的设计中插入了一些乱七八糟的冗余......

+0

这就是这里没有发生什么 - 发生的事情是,当基类正在被初始化时,你正在调用'writeDepth()'函数,这意味着它仍然是基类类型的对象,而不是派生类的类型。 –

+0

感谢您的澄清。你有没有关于设计的建议,所以我可以自动注册Drawable,而不必在每个派生构造函数中做这些事情? –

相关问题