簡體   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