2013-12-13 69 views
1

我想添加我的对象指针到矢量相同的时间对象被创建。目前我已经在对象的构造函数中完成了它,但是现在我已经听说这是一种错误的方法,因为在那个点上对象不是完全创建的。如何在C++中创建对象时将对象指针推向矢量?

的MyObject类的构造函数:

// MyObject constructor 
MyObject::MyObject() { 
    // add object to vector of all objects 
    MyObjectManager::Instance()->objects.push_back(this); 
} 

myObject的是只为对象的基类。我也有从MyObject继承的MyRectangle类,所以当我创建新的MyRectangle时,然后调用MyObject构造函数,并将我新创建的对象推入到MyObjectManager的向量中。

MyObjectManager是一个单例类,它保存所有对象的列表并非常频繁地调用它们的虚拟绘制函数。这是问题吗? MyObjectManager可能会在完全创建对象之前调用对象的Draw函数?

我可以做一个单独的方法来添加对象向量。事情是这样的:

MyObject::Create() { 
    // add object to vector of all objects 
    MyObjectManager::Instance()->objects.push_back(this); 
} 

但后来我不得不用这样的:

MyRectangle *rect = new MyRectangle(0.5, 0.5, 0.1, 0.1); 
rect->Create(); 

我只是希望能够简单地通过构造这样的实例化新的对象:

MyRectangle *rect = new MyRectangle(0.5, 0.5, 0.1, 0.1); 
+0

_'calls他们的虚拟绘图功能非常频繁。这是问题吗?'_很可能! –

+0

你可以看看这个答案的有关在构造函数内调用虚函数的问题http://stackoverflow.com/a/3905886/356440 –

回答

2

你可以在你的构造函数中做到这一点,不是吗?

MyRectangle::MyRectangle(const float& a, const float& b, const float& c, const float& d) { 
    this->Create(); 
} 
+0

这是行不通的吗?如果我在contsructor里面调用Create函数,那么是不是和只是在构造函数中推向矢量一样? – user19985

+0

@ user19985不,它不一样。如果您在MyRectangle构造函数中调用Create,则MyObject构造函数已经完成,那就没问题。正如我在评论中告诉你的那样,你可以看看这个问题的答案stackoverflow.com/a/3905886/356440。 –

+0

@StephaneRolland好的,谢谢。我实际上读了这个答案,但显然不明白一切:) – user19985

0

如果您可以保证在完全构建之前不会访问对象,而只是存储对象,则不会像使用指针那样使用指针。如果有另一个线程处理绘制更新,例如,轮询管理器类中的所有对象并定期调用它们的draw函数,则保证被破坏。

看看this问题和this一个更多的信息。

1

也许你可以考虑使用工厂模式:

MyRectangle * factoryMyRectangle(float x, float y, float w, float h) 
{ 
    MyRectangle *rect = new MyRectangle(x,y,w,h); 
    rect->Create(); 
    return rect; 
} 

,你可以拨打:

MyRectangle *rect = factoryMyRectangle(0.5, 0.5, 0.1, 0.1); 
1

在很大程度上取决于上下文。如果push_back是构造函数中的最后一个 指令,并且没有派生的 类,则应该没有问题。同样,如果你在 一个单线程环境中(并且因为你没有做任何锁定,所以你必须),并且派生类不会做任何事情,通过向量中的指针 ,没有问题。只要您不尝试使用它们指向的实际对象,就可以使用 指针指向尚未完全构建的对象,即 。

这可能是一个问题的一种情况是,如果您在多线程环境中使用基类构造函数 。如果 将指针推向不是完全构造的对象,并且 则另一个线程接管,在 向量中查找该对象,并尝试使用它,则遇到问题。有 各种技术来处理这种情况:最常见的可能是 使用工厂功能来构建所有对象,并有 工厂功能做push_back,构造函数完成后 。所以你永远不会打电话new MyRectangle(...) 以外的工厂功能。 (通常情况下,工厂 功能将是一个静态成员,和构造将是 私有的,这样可以保证这一点。)

请注意,如果你使用的工厂函数,你会probaby 要保持的new在智能指针,直到 push_back结果已完成:

std::unique_ptr<MyRectangle> tmp(new MyRectangle(...)); 
MyObjectManager::Instance()->objects.push_back(tmp.get()); 
tmp.reset() 
2

如果你有特殊MyObjectManager类,你也可以使用它作为一个工厂对象。 要illustarate它充分考虑代码:

struct MyObjectManager { 

    template <typename T, typename... Args> 
    T * createObject(Args... args) { 
     T *ret = new T(args...); 
     m_objects.push_back(ret); 
     return ret; 
    } 

    std::vector<MyObjects *> m_objects; 
}; 

创建对象:

MyRectangle *rect = MyObjectManager::Instance()->createObject<MyRectangle>(1.0, 2.0, 3.0, 4.0); 
+0

谢谢你的回答,这是非常有用的,但这一次我会与Velthune的答案一起去。 – user19985