【问题标题】:How to make class that spawns objects of same class如何制作产生同一类对象的类
【发布时间】:2018-07-26 10:49:23
【问题描述】:

我正在尝试创建一个 particle 类,它能够产生其他粒子,但我自己却陷入了困境!

到目前为止,我创建了一个包含粒子向量的spawner 类。我认为particle 类需要能够“看到”产卵器才能将新粒子添加到这个向量,所以在particle 中我创建了一个指向这个产卵器的指针。然后我希望particle::spawn() 函数会创建一个新粒子并将其添加到向量中,但它会抛出一个错误(“线程 1:EXC_BAD_ACCESS (code=EXC_I386_GPFLT)”)。

为什么这段代码不起作用?是否有一些我想念的更简单的方法来实现这一点?

注意 - 我实际上是使用 pointers 的向量指向 spawner 内的粒子,因为我最终想创建一个带有自己的 spawn() 的子类(例如 particle_sub1)和test() 可以通过多态访问的函数。

谢谢!

#include <iostream>
#include <random>

using namespace std;

// forward declare particle class
class particle;

// --------------------------------
// spawner class
class spawner {
public:
    // vector of pointers to particles
    vector<particle*> particle_ptr_vec;

    spawner() {};
};

// --------------------------------
// particle class
class particle {
public:
    // pointer back to spawner object
    static spawner* spawner_ptr;

    particle() {};
    void set_ptr(spawner &x) {spawner_ptr = &x;}
    virtual void spawn();
    virtual void test() {cout << "pass test\n";}

};

// initialise static variable
spawner* particle::spawner_ptr;

// spawn new particle
void particle::spawn() {
    particle x;
    spawner_ptr->particle_ptr_vec.push_back(&x);
    cout << "spawn particle\n";
}

// --------------------------------
// main funciton
int main(int argc, const char * argv[]) {

    // create spawner
    spawner s;

    // create first particle and define pointer back to spawner
    particle z;
    s.particle_ptr_vec.push_back(&z);
    s.particle_ptr_vec[0]->set_ptr(s);

    // spawn new particle
    s.particle_ptr_vec[0]->spawn();

    // check that two particles exist
    cout << "number of particles: " << s.particle_ptr_vec.size() << "\n";

    // test that worked
    s.particle_ptr_vec[0]->test();  // this test passes
    s.particle_ptr_vec[1]->test();  // this test throws the error
}

【问题讨论】:

    标签: c++ oop polymorphism


    【解决方案1】:

    问题来了

    // spawn new particle
    void particle::spawn() {
        particle x;
        spawner_ptr->particle_ptr_vec.push_back(&x);
        cout << "spawn particle\n";
    }
    

    您在向量中保存了一个指向在您退出方法时被销毁的对象的指针。

    一个答案是动态分配对象,即创建具有无限生命周期的对象,因此您可以控制它们何时被销毁。

    【讨论】:

    • 啊,有道理。我怎样才能避免这种情况?我是否需要spawner 来包含实际粒子以及指向粒子的指针,以免它们被破坏?再次感谢!
    • 最基本的方法是使用new。 IE。 spawner_ptr-&gt;particle_ptr_vec.push_back(new particle);。但实际上,这是一个巨大的话题,有很多复杂性和替代的做事方式。你真的需要一本好书。
    • @bobverity 存储对象和指针没有多大意义,如果你有对象,你总是可以得到一个指向它的指针。但是仅存储对象是一种替代方法,具体取决于您要实现的目标。请参阅 maxim 的答案。
    • 我使用指针的原因是我想使用函数多态性,例如particle_sub1 类有自己的spawn() 函数,但仍然可以存储在particle_ptr_vec 中。我发现如果我将particle_ptr_vec 设为粒子向量而不是指向粒子的指针,那么我总是会得到基类行为。您的new particle 建议似乎已经修复了它,但我担心内存泄漏,因为我不确定在哪里/如何销毁这个对象。
    • @bobverity 这正是问题所在。一种简单的解决方案(可能不适合您)是使用 unqiue_ptr。矢量>particle_ptr_vec。现在您的向量拥有指针并将删除它们。问题是只能有一个所有者,因此您必须小心复制 unque_ptr,因为这样做会转移所有权。正如我所说,这是一个很大的话题,有很多可能的方法。
    【解决方案2】:

    按值存储粒子以解决您的问题:vector&lt;particle&gt; particle_ptr_vec;。然后spawner_ptr-&gt;particle_ptr_vec.push_back({});

    【讨论】:

      【解决方案3】:

      您正在尝试解决面向对象的问题,这更适合函数式风格。这会给您带来麻烦,因为您的对象现在正在管理其他粒子的数据,而不仅仅是它们自己的。这与 OOP 中使用的封装原则背道而驰。

      我建议这样做:

      auto particles = std::vector<particle>{};
      
      //initialize some values into particles...
      
      //define a new particle list or the for each syntax does not work
      auto new_particles = std::vector<particle>{};
      
      for (auto&& current : particles)
          if (current.needs_to_spawn_new_particles())
              for (auto&& new_particle : current.new_particles())
                  new_particles.emplace_back(new_particle);
      
      //update particles with new_particles
      

      这甚至为您提供了扩展功能的空间:

      for (auto&& current : particles) {
          current.update();
          if (current.needs_to_spawn_new_particles())
              for (auto&& new_particle : current.new_particles())
                  new_particles.emplace_back(new_particle);
          else if (!current.needs_to_be_destroyed())
                  new_particles.emplace_back(current);
      }
      

      现在它会为您提供new_particles 向量中的所有粒子(已删除被破坏的粒子)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-02-02
        • 2021-09-10
        • 1970-01-01
        • 2014-01-12
        • 1970-01-01
        • 2021-01-22
        • 2021-05-08
        • 1970-01-01
        相关资源
        最近更新 更多