繁体   English   中英

为什么我的向量在 c++ 中存储了我的 object 的副本,而不是原始值?

[英]Why does my vector store a copy of my object, and not the original value, in c++?

我有一个中期任务,我们为我们课程中的一个程序进行 3 组单元测试和文档等。 我选择的程序是物理模拟。

在这个程序中,有两个类, ThingWorld 我能够独立创建这些对象。 我尝试通过创建std::vector<Thing> thingsThing object 添加到World object ,然后创建vector以将Thing添加到 things. 但是,当我这样做时,似乎World object 创建了自己的Thing副本,因为当我更改Thing的 position 时,Thing 向量中的Thing版本保持不变。

请就此事提供一些指导,我觉得我的问题可能在于我在这种情况下如何使用指针。

 void testBoundaryBounce()
 {
      //Create the world
      World world{10.0f, 10.0f, 1.0f};
      //Thing, 2 units away from boundary
      Thing thing{8.0f, 5.0f, 1.0f};
      //Add thing to world (adding it the the things vector)
      world.addThing(&thing);
      //Apply force that should trigger bounce back to x = 7
      thing.applyForce(1.0f, 0.0f);
      //Updating thing so that movement takes effect
      thing.update();
      //Running world update to account for collisions, bounces etc
      world.update();

      std::cout << "thing x : " << thing.getX() << std::endl;

      CPPUNIT_ASSERT(thing.getX() == 7);
 }


Thing::Thing(float x, float y, float radius)
: x{x}, y{y}, dX{0}, dY{0}, radius{radius}
{

}


World::World(float width, float height, float gravity)
: width{width}, height{height}, gravity{gravity}
{
    std::vector<Thing> things;
}



void World::addThing(Thing* thing)
{
    float thingX = thing->getX();
    float thingY = thing->getY();
    float thingRad = thing->getRad();

    std::cout << "Radius : " << thingRad << std::endl;

    if (thingX + thingRad > width || thingX - thingRad <= 0 || thingY + thingRad > 
    height|| thingY - thingRad <= 0)
    {
        std::cout << "Thing is out of bounds or is too large" << std::endl;
    }
    else {
        std::cout << "Thing is good" << std::endl;
        things.push_back(*thing);
    }
}

void World::update()
{
    for (Thing& thing : things)
    {
        thing.update();
        float thingX = thing.getX();
        float thingY = thing.getY();
        float thingRad = thing.getRad();
        float worldGrav = this->gravity;

        std::cout << "thing x: " << thingX << std::endl;
        std::cout << "thing rad: " << thingRad << std::endl;

        //World Boundary Bounces
        if (thingX + thingRad >= width)
        {
            std::cout << "Bounce left" << std::endl;
            thing.applyForce(-2.0f, 0.0f);
            thing.update();
        }
        if (thingX + thingRad <= 0)
        {
            thing.applyForce(2.0f, 0.0f);
            thing.update();
            std::cout << "Bounce right" << std::endl;
        }
        if (thingY + thingRad >= height)
        {
            thing.applyForce(0.0f, -2.0f);
            thing.update();
            std::cout << "Bounce up" << std::endl;
        }
        if (thingY - thingRad <= 0)
        {
            thing.applyForce(0.0f, 2.0f);
            thing.update();
            std::cout << "Bounce down" << std::endl;
        }
        //Thing Collision Bounces
        for (Thing& otherthing : things)
        {
            float thing2X = otherthing.getX();
            float thing2Y = otherthing.getY();
            float thing2Rad = otherthing.getRad();
            if (thingX + thingRad == thing2X + thing2Rad && thingY + thingRad == 
                thing2Y + thing2Rad)
            {
                thing.applyForce(-2.0f, -2.0f);
                thing.update();
                otherthing.applyForce(2.0f, 2.0f);
                otherthing.update();
            }
        }
        //Gravitational Pull
        thing.applyForce(0.0f, worldGrav);
    }
}

它在void push_back (const value_type& val);的定义中是正确的; ...

在当前最后一个元素之后,在向量的末尾添加一个新元素。 val 的内容被复制(或移动)到新元素。

所以当你打电话给things.push_back(*thing); ,您正在向“事物”向量添加一个新元素,该元素是thing指针指向的值的副本。

你想改变你的向量来保存指向Thing类型的指针:

std::vector<Thing *> things;

并添加指针而不是副本:

things.push_back(thing);

请注意,您稍后必须通过->而不是. ,或者您可以创建对它的引用,例如:

    for (Thing* pt: things)
    {
        Thing& thing = *pt; 
        thing.update();
        //etc...

您可以让World构造它拥有的Thing ,而不是构造一个Thing并将其复制到world

void testBoundaryBounce()
 {
      //Create the world
      World world{10.0f, 10.0f, 1.0f};
      //Thing, 2 units away from boundary
      Thing * thing = world.addThing(8.0f, 5.0f, 1.0f);
      //Apply force that should trigger bounce back to x = 7
      thing->applyForce(1.0f, 0.0f);
      //Running world update to account for collisions, bounces etc
      //Implies updating all the things
      world.update();

      std::cout << "thing x : " << thing.getX() << std::endl;

      CPPUNIT_ASSERT(thing.getX() == 7);
 }


Thing::Thing(float x, float y, float radius)
: x{x}, y{y}, dX{0}, dY{0}, radius{radius}
{

}


World::World(float width, float height, float gravity)
: width{width}, height{height}, gravity{gravity}
{
    std::vector<Thing> things;
}



Thing * World::addThing(float x, float y, float radius)
{
    std::cout << "Radius : " << radius << std::endl;

    if ((x + radius > width) || (x - radius <= 0) || (y + radius > 
    height) || (y - radius <= 0))
    {
        std::cout << "Thing is out of bounds or is too large" << std::endl;
        return nullptr;
    }
    else 
    {
        std::cout << "Thing is good" << std::endl;
        return &things.emplace_back(x, y, radius);
    }
}

void World::update()
{
    for (Thing& thing : things)
    {
        thing.update();
        float thingX = thing.getX();
        float thingY = thing.getY();
        float thingRad = thing.getRad();
        float worldGrav = this->gravity;

        std::cout << "thing x: " << thingX << std::endl;
        std::cout << "thing rad: " << thingRad << std::endl;

        //World Boundary Bounces
        if (thingX + thingRad >= width)
        {
            std::cout << "Bounce left" << std::endl;
            thing.applyForce(-2.0f, 0.0f);
            thing.update();
        }
        if (thingX + thingRad <= 0)
        {
            thing.applyForce(2.0f, 0.0f);
            thing.update();
            std::cout << "Bounce right" << std::endl;
        }
        if (thingY + thingRad >= height)
        {
            thing.applyForce(0.0f, -2.0f);
            thing.update();
            std::cout << "Bounce up" << std::endl;
        }
        if (thingY - thingRad <= 0)
        {
            thing.applyForce(0.0f, 2.0f);
            thing.update();
            std::cout << "Bounce down" << std::endl;
        }
        //Thing Collision Bounces
        for (Thing& otherthing : things)
        {
            float thing2X = otherthing.getX();
            float thing2Y = otherthing.getY();
            float thing2Rad = otherthing.getRad();
            if (thingX + thingRad == thing2X + thing2Rad && thingY + thingRad == 
                thing2Y + thing2Rad)
            {
                thing.applyForce(-2.0f, -2.0f);
                thing.update();
                otherthing.applyForce(2.0f, 2.0f);
                otherthing.update();
            }
        }
        //Gravitational Pull
        thing.applyForce(0.0f, worldGrav);
    }
}

顺便说一句,每次更新都会自动反弹

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM