在我的class
实施中,我有类似的内容:
基类
class swcWidget :
public swcRectangle
{
public:
swcWidget();
virtual ~swcWidget();
void update(float dt);
protected:
inline virtual void oPaintOnTop() { }
private:
};
派生类
class swcButton :
public swcWidget
,public swcText
{
public:
swcButton();
virtual ~swcButton();
static const int DEFAULT_SIZE = 20;
protected:
private:
void oPaintOnTop();
};
class swcApplication
{
public:
swcApplication(int argc, char *argv[]);
virtual ~swcApplication();
int run();
struct Controls
{
typedef std::vector<swcWidget*> vWidgets; //option 1
~Controls();
/////////////////////////////////
// M A I N P R O B L E M //
/////////////////////////////////
void add(swcWidget &&widgets); //most preferred option
//but gets demoted to base class.
void add(swcWidget *widgets); //second choice
//but should I make a copy of it?
//or just make a reference to it?
//and this one does what I wanted to.
//but still unsure on other things I don't know
void add(swcWidget *&&widgets); //this compiles fine (?)
//I don't know what kind of disaster I can make into this, but still does not do what I wanted.
inline vWidgets &getWidgets() {
return widgets;
}
private:
vWidgets widgets;
};
Controls controls;
};
我知道一些像这样的工作选项:
制作
swcApplication::Controls::widgets
作为
的类型std::vector<std::shared_ptr<swcWidget>>
但我的代码将绑定到std::shared_ptr
,我不能像这样编写简单的语法:
swcButton btn;
app.controls.add(std::move(btn));
使用示例:
的main.cpp
int main(int argc, char *argv[])
{
swcApplication app(argc, argv);
app.windows.create(640, 480);
if (font->load("fonts\\georgia.fnt") != BMfont_Status::BMF_NO_ERROR)
{
puts("failed to load \"georgia.fnt\"");
}
{
swcButton btn;
btn.setPosition(100, 100);
btn.setFont(font);
btn.text = "Ey!";
app.controls.add(std::move(&btn));
// btn.text = "Oy!";
}
return app.run();
}
更新
这里是swcApplication::Controls::add()
的临时定义,尽管它可能仍然有所不同
void swcApplication::Controls::add(swcWidget &&widget)
{
widgets.push_back(std::move(widget));
}
答案 0 :(得分:1)
如果一个类是可移动的,那么它将依次移动它的成员。为了提高效率,这些成员必须是小POD或必须在堆上分配。您必须添加此功能,不要忘记移动任何成员,并且需要注意对象切片。
鉴于该类是非平凡的,当您直接使用指针时(当然是以堆分配时间为代价),您可以使用最有效的移动构造。没有切片是可能的,并且不会忘记移动任何成员,因为您可以一次移动整个对象。需要注意的一个障碍是跟踪谁拥有指针 - 你最好把它设置在石头上,但如果这样做了,那么就不再有问题了。
移动语义很棒,但是如果你的课程有些参与,我认为在这种情况下的指针更容易/更有效地使用。因此,我坚持使用指针变体,并确保您的集合将拥有指针(并通过RAII再次释放它们) - 在您的公共接口中自由使用注释这样说。您可以通过存储某种形式的智能指针(提示:小心使用unique_ptr!)或(安全性较低)make来执行此操作,并始终使用Clear()成员在清除()集合之前删除所有指针。
修改
将小部件成员定义为vector类型时,示例代码可以是:
要为swcApplication类添加:
void swcApplication::Controls::ClearWidgets() {
for (auto& nextWidget: widgets) {
delete nextWidget;
}
widgets.clear();
}
不要忘记在适当的时候调用ClearWidgets(比如在析构函数中)。
添加小部件可以通过以下方式完成:
// Note: any passed widget will not be owned by you anymore!
template <typename Widget>
void swcApplication::Controls::add(Widget*& widget) {
widgets.push_back(widget);
widget = nullptr;
}
从现在开始,您可以添加
等小部件swcButton* btn = new swcButton;
app.controls.add(btn);
// btn is now owned by app.controls, and should be set
// to nullptr for you to prevent misuse like deleting it
在这里使用智能指针应该使它更安全,尽管存储unique_ptr使得访问它们有点容易出错(注意在访问它时从容器中取回所有权),而shared_ptr会给出可能不需要的开销。