簡體   English   中英

對象指針的全局向量錯誤C ++

[英]Error with global vector of object pointers c++

我正在用c ++開發2D物理引擎,而我正在使用的主要結構之一就是RigidBody。 為了在每個時間步驟中輕松遍歷所有RigidBody對象,我嘗試創建RigidBody對象指針的全局向量。

vector<RigidBody*> RigidBodies

正如其他StackOverflow答案中所建議的那樣,我在頭文件中聲明了全局變量,並在其他項目.cpp文件之一中對其進行了定義。 但是,當我嘗試訪問成員函數或變量時,我得到了虛假值。 以下是我的源文件和頭文件。 有人可以讓我知道這是否有錯誤,或者我做的是根本上錯誤的事情,因為我已經嘗試了幾天,但還沒有找到答案。

main.cpp中:

#include <iostream>
#include <vector>
#include "polygon.h"
#include "rendering.h"

int test;

std::vector<RigidBody*> RigidBodies;
RigidBody * rigPtr;

void CreateBody() {
  Material m1;  // Settings for ROCK.
  m1.density = 0.6;
  m1.restitution = 0.1;
  float volume = 1;
  Vector p0 = {0,1};
  Vector p1 = {1,1};
  Vector p2 = {1,0};
  Vector p3 = {0,0};
  std::vector<Vector*> Points;
  Points.push_back(&p0);
  Points.push_back(&p1);
  Points.push_back(&p2);
  Points.push_back(&p3);
  //std::cout << Points.at(0)->y << '\n';
  Polygon pol1(Points, m1, volume);
  Polygon * polPtr  = &pol1; 
  //std::cout << pol1.Points.at(0)->y << '\n';
  std::cout << "polygon created" << '\n';
  Vector pos1;
  pos1.x = 10;
  pos1.y = 10;
  RigidBody r1(pos1, polPtr);
  rigPtr = &r1;
  std::cout << "rigid body created" << '\n';
 // std::cout << RigidBodies.at(0)->dt << '\n';

}

// MAIN
int main() {

  test = 3;
  //std::cout << test << '\n';
  test = 6;

  CreateBody();

  RigidBodies.push_back(rigPtr);

  //std::cout << test << '\n';

    unsigned int lastTime = SDL_GetTicks();
    unsigned int currentTime;

    SDL_Renderer* renderer = InitializeRender();

    while(1) {
    currentTime = SDL_GetTicks();
    if (currentTime - lastTime > 33) {
        //RigidBodies.at(0)->Step();
        Render(renderer, RigidBodies);
        lastTime = SDL_GetTicks();
    }
    }
  return(0);
}

rendering.cpp:

#include <iostream>
#include "polygon.h"
#include "rendering.h"



SDL_Renderer* InitializeRender() {
      SDL_Window * window = NULL;
    window = SDL_CreateWindow
    (
        "RIGID BODIES SIM", SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        640,
        480,
        SDL_WINDOW_SHOWN
    );

    // Setup renderer
    SDL_Renderer * renderer = NULL;
    renderer =  SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    return(renderer);
}

void Render(SDL_Renderer * renderer, std::vector<RigidBody*> RigidBodies) {
    float scale = 10;  // METERS to PIXELS.
  SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);  // Clear screen.
  SDL_RenderClear(renderer);
  SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);  // Set polygon drawing color (GREEN)
  std::cout << RigidBodies.at(0)->dt << '\n';
  for (int j = 0; j < RigidBodies.size(); j++) {
    RigidBody * rPtr = RigidBodies.at(j);  // Not recognizing rigid body pointer correctly
    //std::cout << rPtr->dt << '\n';
    Polygon * polyPtr = rPtr->p;
    std::cout << "hey1" << '\n';
    int size = polyPtr->Points.size();  // ERROR HERE //
    std::cout << "hey2" << '\n';
  //  std::cout << polyPtr->Points.at(0)->y << '\n';
    for (int i = 0; i < size; i++) {
      std::cout << "hey3" << '\n';
        auto pointPtr1 = polyPtr->Points.at(i);
      int lastIndex = size - 1;
      //std::cout << i+1 << '\n';
        auto pointPtr2 = polyPtr->Points.at((i + 1) % (lastIndex));  // Modulo so last point links back up to first one.
      SDL_RenderDrawLine(renderer, (rPtr->position.x + pointPtr1->x) * scale, SCREEN_HEIGHT 
        - (rPtr->position.y + pointPtr1->y) * scale, (rPtr->position.x + pointPtr2->x) * scale,
        SCREEN_WIDTH - (rPtr->position.y + pointPtr2->y * scale));
    }
  }
  SDL_RenderPresent(renderer);
}

rendering.h:

#include <vector>
#include <SDL2/SDL.h>

#ifndef RENDERING_H
#define RENDERING_H

//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

//SDL_Renderer * renderer; 

SDL_Renderer* InitializeRender();
void Render(SDL_Renderer*, std::vector<RigidBody*>);

#endif

rigid_bodies.cpp

// Joaquin Matias Giorgi jmgiorgi@bu.edu Impulse-Based Physics Engine 2D //
#include <iostream>
#include <math.h>
#include <SDL2/SDL.h>
#include <vector>
#include "polygon.h"

using namespace std;

vector<RigidBody*> RigidBodies;

// VECTOR STUFF //
  // Multiplication by scalar quantity.
  Vector Vector::operator*(const float scalar) {
      Vector vout;
      vout.x = this->x * scalar;
      vout.y = this->y * scalar;
      return(vout);
  }
  // Addition overload.
  Vector Vector::operator+=(const Vector vec) {
    Vector vout;
    vout.x = this->x + vec.x;
    vout.y = this->y + vec.y;
    return(vout);
  }

float dot (Vector vec1, Vector vec2) {
    float out = (vec1.x * vec2.x) + (vec1.y * vec2.y);
    return(out);
}

float cross2d (Vector vec1, Vector vec2) {
    // magnitude of perpendicular vector in 3d case.
    float out = (vec1.x * vec2.y) - (vec1.y * vec2.x);
    return(out);
}

// POLYGON Struct Methods //

Polygon::Polygon(vector< Vector* > Points1, Material m1, float volume1) {
    Points = Points1;
    m = m1;
    volume = volume1;
  }

 float Polygon::ComputeMass() {
    float mass = m.density * this->volume;
    return(mass);
 }
 // RIGID BODY Struct Methods //

    RigidBody::RigidBody(Vector position1, Polygon * p1) {

    std::cout << test << '\n';

    position = position1;
    p = p1;
    mass = p1->ComputeMass();
    orientation = 0;
    angularVelocity = 0;
    dt = .033;
    gravity.x = 0;
    gravity.y = -9.8;
    velocity.x = 0;
    velocity.y = 0;
    //RigidBodies.push_back(this); // Push to global vector of all RigidBodies.
    }

  // UPDATE at each iteration.  
    void RigidBody::Step() {
    this->velocity += this->gravity * this->dt;
    this->position += this->velocity * this->dt;
    this->orientation += this->angularVelocity * this->dt;
    }

polygon.h:

#include <vector>

#ifndef POLYGON_H
#define POLYGON_H

struct Vector {
    float x;
    float y;
  // Multiplication by scalar quantity.
  Vector operator*(const float);
  // Addition overload.
  Vector operator+=(const Vector);
};

struct Material {
    float density;
    float restitution;
};

struct Polygon {
  std::vector< Vector* > Points;
  float volume;
  Material m;

  Polygon(std::vector< Vector* >, Material, float);
  float ComputeMass();
};

struct RigidBody {
    float mass;
    float volume;
    float dt;
    // Linear
    Vector position;
    Vector gravity;
    Vector velocity;
    float acceleration;
    // Angular
    float orientation;
    float angularVelocity;
    float torque;
    Polygon * p;
  // Constructor
    RigidBody(Vector, Polygon*);
  // UPDATE at each iteration.  
    void Step();
};

// DECLARATION
extern std::vector<RigidBody*> RigidBodies;  // Global Vector of RigidBody Pointers.


#endif

Makefile文件:

sim: 
    g++ -std=c++11 main.cpp rigid_bodies.cpp rendering.cpp -I include -L lib -l SDL2-2.0.0

在您的函數CreateBodyRigidBody r1在堆棧上創建,並且在函數返回時不再存在。 函數結束后,指針rigPtr (以及PointspolPtr的指針)不再有效。 如果您在循環中調用CreateBody ,則可能會看到每次調用都獲得相同的指針。

最簡單的解決方案是根本不使用指針,因為您的對象非常小,並且復制不應該太昂貴(或者移動起來更便宜)。

如果您真的想使用指針,則需要在堆上分配對象,而不是使用new分配堆棧。 請注意,然后需要使用delete將這些對象釋放。 一種更安全的解決方案是將指針包裝在std::shared_ptrstd::unique_ptr ,以自動刪除對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM