1

更新:

正如神经元所建议的,我尝试输出向量的地址,在整个程序中都是一样的。这意味着没有重复发生;在定义了 Planet 和 Player 之后但在程序进入 setup() 和 render() 之前,向量以某种方式得到“重置”。这可能是什么原因造成的?

更新 2:

使用 cout,我确定错误发生在 main() 之前。所以全局的 Player 和 Planet 对象被构造出来,指向它们的指针被添加到 MasterEntityVector 中。然后,在 main() 启动之前(或 main() 启动,但在它的任何部分执行之前),MasterEntityVector 得到“重置”,之后一切都按预期运行。当 MasterEntityVector 是 CircularEntity 类的静态成员以及 MasterEntityVector 是 OpenGLLoopLogic.ccp 中的全局成员时,都会发生此行为。什么可能导致这种行为?我认为这可能与“静态初始化顺序惨败”有关http://www.parashift.com/c++-faq-lite/static-init-order.html但问题似乎略有不同(对于例如,我没有崩溃)。

更新 3:

我不知道为什么它不起作用,但我找到了有同样问题和解决方案的人。请看下面我的回答。我将删除整个项目的包含(将问题缩小到其原始大小),因为在链接中查看 Alex 的问题时,更大的项目似乎与问题无关。


如果我的错误是微不足道的,我会提前道歉。我是一个 C++ 初学者,对范围和多文件项目的概念掌握得比较差,所以虽然我花了很多时间玩代码并在 Internet 上搜索答案,但我可能错过了一些明显的东西。

为了让我的问题更容易回答,下面的代码被简化了。

我正在使用代码块、C++、OpenGL(用于图形)和 SDL(用于窗口)。

添加了 cout 行以进行故障排除,我将在下面包含输出。

问题是一个名为 MasterEntityVector 的全局向量,它应该包含指向我的模拟中所有“实体”的指针。它在 CircularEntity.ccp 中声明,在 CircularEntity.h 中有一个 extern。应该在实体的构造函数期间将指针添加到它。在 OpenGLLoopLogic.ccp 中,在创建实体时将指针添加到 MasterEntityVector,但是当我们开始进入 init/setup/render 函数时,它似乎要么被重置,要么得到它的第二个实例。如何阻止这种不良行为?

循环实体.h:

#ifndef CIRCULARENTITY_H
#define CIRCULARENTITY_H

#include "LUtil.h"

class CircularEntity {
    public:
        CircularEntity(double x, double y, int r);
        double xpos, ypos;
        int radius;
        void Draw(double camxpos, double camypos);

};

extern std::vector<CircularEntity *> MasterEntityVector;  //contains pointers to ALL entities

#endif // CIRCULARENTITY_H

循环实体.ccp:

#include "CircularEntity.h"

std::vector<CircularEntity *> MasterEntityVector;  //contains pointers to ALL entities

CircularEntity::CircularEntity(double x, double y, int r) {
    radius = r;
    xpos = x;
    ypos = y;
    std::cout << "test 1" << std::endl;
    std::cout << MasterEntityVector.size() << std::endl;
    MasterEntityVector.push_back(this);
    std::cout << "test 2" << std::endl;
    std::cout << MasterEntityVector.size() << std::endl;
}

...
//irrelevant code removed
...

OpenGLLoopLogic.h:

#ifndef OPENGLLOOPLOGIC_H
#define OPENGLLOOPLOGIC_H

#include "MoveableCircular.h"

//Screen constants
const int SCREEN_WIDTH = 1800;
const int SCREEN_HEIGHT = 1000;

bool initGL();
    
void setup();

void update();
    
void render();
    
void handleKeys( unsigned char key, int x, int y );

#endif // OPENGLLOOPLOGIC_H

OpenGLLoopLogic.ccp:

#include "OpenGLLoopLogic.h"

//The projection scale
GLfloat gProjectionScale = 1.f;
MoveableCircular Player(200, 200, 0, 0, .05, 10);
CircularEntity Planet(0, 0, 100);

bool initGL()
{
    ...
    //irrelevant code removed
    ...
    setup();

    return true;
}

void setup() {
    CircularEntity Planet2(0, 0, 100);
    CircularEntity Planet3(0, 0, 100);
}

void velocityupdate()
{
    Player.Gravity(0,0,100);
}

void positionupdate()
{
    Player.PositionUpdate();
}

void update()
{
        velocityupdate();
        positionupdate();
}

void render()
{
    ...
    //irrelevant code removed
    ...
    for (int n=0; n<MasterEntityVector.size(); n += 1) {
        (*MasterEntityVector[n]).Draw(Player.xpos, Player.ypos);
        std::cout << MasterEntityVector.size() << std::endl;
    }

    ...
    //irrelevant code removed
    ...
}

void handleKeys( unsigned char key, int x, int y )
{
    ...
    //irrelevant code removed
    ...
}

我省略了几个文件,所以你们都没有阅读大量不相关的代码:

MoveableCircular 源代码和标头与 CircularEntity 文件非常相似。(cout 的测试 3 和 4 而不是 1 和 2,MoveableCircular 类继承自 CirularEntity,它只是有一个重新定义的构造函数)。main.ccp 调用 init,然后有一个循环:处理键,更新,然后渲染。“包含树”中“高于”MoveableCirular.h 的文件(我不知道正确的术语)与该问题无关,他们所做的唯一与该问题真正相关的是“#包括 ”

输出是:

test 1
0
test 2
1
test 3
1
test 4
2
test 1
2
test 2
3
test 1
0
test 2
1
test 1
1
test 2
2
2
2
2
.
.
.
[infinite 2's]

正如您从输出中看到的那样,随着 Player 和 Planet 对象的构建,一切正常。但是,当我们进入 OpenGLLoopLogic 函数(设置中的 Planet2 和 Planet3、绘制代码渲染等)时,它似乎“重置”或创建了 MasterEntityVector 的第二个副本。这种不良行为的原因是什么?

我已经尝试过的事情:

在 MasterEntityVector 之前的整个代码中添加“::”

命名空间的东西(虽然我对命名空间的知识和理解确实很薄弱,所以这仍然可能是问题的根源)。

4

3 回答 3

2

我仍然不知道为什么我做错了,但这里有一个相同问题的链接,并为遇到类似问题的任何人提供了修复:

全局向量在调用之间清空自身?

请参阅 ZeRemz 的解决方案。

就我而言,我使用/添加了以下代码:

在 CircularEntity.h 中:

std::vector<CircularEntity *> &getMasterEntityVector();

在 CircularEntity.ccp 中:

std::vector<CircularEntity *> &getMasterEntityVector()
{
    static std::vector<CircularEntity *> s_vector;
    return s_vector;
}

我仍然不知道为什么我的原始实现(或者为什么 Alex 在链接中的原始实现)是错误的,而且我从不喜欢不知道为什么,但至少我们有一个解决方案!

于 2013-05-27T17:35:42.380 回答
0

只需忘记extern任何命名空间中的static变量并在CircularEntity类(或另一个类,如Entities)内使用变量。

//CircularEntity.h:
class CircularEntity {
  public:
    static vector<CircularEntity*> entities;
}

//CircularEntity.cpp
vector<CircularEntity*> CircularEntities::entities;

...
CircularEntities::entities.push_back(whatever);

这样一切都将更加封装。

于 2013-05-26T23:10:42.917 回答
0

我已经阅读了几乎所有代码,但仍有一些问题:

  • 在您的代码MasterEntityVector中仅在CircularEntity. 是否在其他任何地方引用了它,尤其是它pop_backerase或任何非 const 方法?
  • 的对象CircularEntity及其子类,它们是在哪里构造的?
  • 你没有CircularEntity::~CircularEntity超载,是吗?

对于后两个问题,我在那里发现了一个错误(?)

void setup() {
    CircularEntity Planet2(0, 0, 100);
    CircularEntity Planet3(0, 0, 100);
}

您在本地构建了 2 s,因此在调用CircularEntity后它们将被破坏。如果您正确编写,则必须从 中删除,从而减小向量的大小。(但我没有看到 的声明)setup()initGL()~CircularEntitythisMasterEntityVector~CircularEntity

此外,如果您怀疑是否有另一个实例,我认为您可以尝试输出全局向量的地址。

于 2013-05-27T02:54:18.143 回答