2017-09-05 45 views
1

在一个Qt相关的代码我试图通过以下的方法,以减少一些重复的线:如何转移QPainter? (从工厂功能移动对象)

QPainter createPainter(const QColor& color) 
{ 
    QPainter painter(&m_image); 
    painter.setBrush(color); 
    painter.setPen(color); 
    return painter; 
} 

但是QPainter的拷贝构造函数被明确地删除。它应该不是C++ 11中的问题,但遗憾的是它不可移动。这是否有任何理由,还是仅仅是一个API缺陷? 这是否是createPainter的好解决方案(除了提供move-ctor)?

  • 它可以接受一个QPainter引用,但这会降低该方法的含义,并会给调用者的代码添加噪声。
  • 它可能会返回一个unique_ptrQPainter,但它会引入堆分配开销。
  • ...还有其他想法吗?

感谢您的回复!

+0

为什么不使用指针?像:'QPointer * p = new QPainter(&m_image); ...返回p;'? – vahancho

+0

我不想在堆上分配对象,只是为了提取三行代码。 (在这种情况下,我会使用智能指针确保画家在任何情况下都能正常释放) – titapo

+0

如果您要传输对象的所有权或以其他方式处理对象,则使用智能指针是有意义的。我没有看到你在这里需要它。不要以为使用“智能”指针会让你的代码更加智能化。 – vahancho

回答

2

一个窍门是恒定的基准返回:

选项1:

QPainter createPainter(const QColor& color) //definitely return by value 
{ 
    QPointer painter(&m_image); 
    painter.setBrush(color); 
    painter.setPen(color); 
    return painter; 
} 

则执行以下操作:

const QPainter& painter = createPainter(const QColor& color); 

通过C++标准,这保证了没有复制将会发生,但返回值的寿命将延长。

选项2:

用户共享或唯一的指针。我知道你说他们有开销,但这没什么,假设你没有开发游戏引擎,而且这是主流(我确定你没有在这样的游戏引擎中使用Qt)。

方案3:

如果这些让你快乐,我会建议我讨厌的解决方案,只是为了完整性。使用宏!

#define CreatePainter(painter_name) \ 
QPointer painter_name(&m_image); \ 
painter_name.setBrush(color);  \ 
painter_name.setPen(color);  

要使用它:

CreatePainter(painter); 
painter.begin(); 
//... 

编辑:

选项4: 我刚刚学会(感谢昆汀),这是合法的:

QPainter createPainter(const QColor& color) //definitely return by value 
{ 
    QPointer painter(&m_image); 
    painter.setBrush(color); 
    painter.setPen(color); 
    return painter; 
} 

那么这个:

QPainter&& painter = createPainter(const QColor& color); 

查阅参考文献here。这是一种新的C++ 11解决方案,可以在不使其成为常量的情况下延长对象的生命周期。

+0

我喜欢选项1!不幸的是,drawing是一个非常量操作,所以在当前情况下它不起作用。 – titapo

+0

@titapo然后我会告诉你世界上最糟糕的建议:使用'const_cast'(no!只是在开玩笑:))。我看到的唯一合法解决方案是宏。 –

+0

如果函数按值返回对象(选项1),如何避免复制? – vahancho

0

正如想法

struct ColoredPainter : public QPainter { 
ColoredPainter (device, color) : QPainter (device) 
setBrush(color); 
setPen(color); 
}; 

... 

ColoredPainter painter(m_Image, color); 

但我不喜欢这个主意。看起来像重复的代码部分看起来是一样的,但把它放到独立块中是没有意义的。这将很难理解这种类甚至功能。