循环依赖性头痛

Circular dependency headache

本文关键字:依赖性 循环      更新时间:2023-10-16

最初的问题是我有三个类ABCA有一个链接并调用B,它有一个链接并调用C。但是C调用A静态方法。我只是无法让这个静态调用工作。

但是伙计们抱怨我在截断代码时有些不准确,所以类的真实名称是GameRendererGameViewFieldViewGameRenderer有一个链接并调用GameView,它有一个链接并调用FieldView。但是FieldView调用GameRenderer静态方法createGlTextureFromResource。我只是无法让这个静态调用工作。

这是完整和真实的标题 GameRenderer.h

// GameRenderer.h
#ifndef GAME_RENDERER
#define GAME_RENDERER
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
namespace game{
class GameModel;
class GameView;
class GameRenderer {
jobject*    context;
jobject*    gameOverHandler;
static JNIEnv*     env;
static jobject*    jparent;
GameModel*  gameModel;
GameView*   gameView;
glm::mat4 mProjMatrix;
glm::mat4 mVMatrix;
public:
GameRenderer(jobject* context, jobject* gameOverHandler, JNIEnv* env, jobject* jparent);
void onSurfaceCreated();
void onDrawFrame();
void onSurfaceChanged(int width, int height);
void setMotionDirection();
static int* getImagePixels (int imageId, int width, int height);
static void createGlTextureFromResource (int resourceId, int textureId);
};
}
#endif 

游戏视图.h

// GameView.h
#ifndef GAME_VIEW
#define GAME_VIEW
#include <glm/glm.hpp>
namespace game{
class GameModel;
class FieldView;
class GameView {
GameModel* gameModel;
FieldView* fieldView;
public:
GameView(GameModel* gameModel);
void draw(glm::mat4 mProjMatrix, glm::mat4 mVMatrix);
};
}
#endif 

FieldView.h

// FieldView.h
#ifndef FIELD_VIEW
#define FIELD_VIEW
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include "GLESUtils.h"
namespace game{
class GameRenderer;
class FieldView {
static const int FLOAT_SIZE_BYTES = 4;
static const int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
static const int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
static const int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
glm::mat4 mMMatrix;
glm::mat4 mMVPMatrix;
int mProgram;
int mTextureID;
int muMVPMatrixHandle;
int maPositionHandle;
int maTextureHandle;
public:
FieldView();
void draw(glm::mat4 mProjMatrix, glm::mat4 mVMatrix);
};
}
#endif 

这是FieldView的剪切版本.cpp

// FieldView.cpp
#include <jni.h>  
#include <string.h>  
#include <android/log.h>  
#include "FieldView.h"
#include "GameRenderer.h"
#define  LOG_TAG    "NDK_FieldView"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
namespace game{
static GLfloat mTriangleVerticesData[] = {...};
static const char mVertexShader[] = "...n";
static const char mFragmentShader[] = "...n";
FieldView::FieldView() {
mProgram            = -1;
mTextureID          = -1;
muMVPMatrixHandle   = -1;
maPositionHandle    = -1;
maTextureHandle     = -1;
mProgram = GLESUtils::createProgram(mVertexShader, mFragmentShader);
GLESUtils::checkGlError("createProgram mProgram");
if (mProgram == 0) {
LOGI("program not created exiting");
return;
}
maPositionHandle = glGetAttribLocation(mProgram, "aPosition");
GLESUtils::checkGlError("glGetAttribLocation aPosition");
if (maPositionHandle == -1) {
return;
}
maTextureHandle = glGetAttribLocation(mProgram, "aTextureCoord");
GLESUtils::checkGlError("glGetAttribLocation aTextureCoord");
if (maTextureHandle == -1) {
return;
}
muMVPMatrixHandle = glGetUniformLocation(mProgram, "uMVPMatrix");
GLESUtils::checkGlError("glGetUniformLocation uMVPMatrix");
if (muMVPMatrixHandle == -1) {
return;
}
/*
* Create our texture. This has to be done each time the
* surface is created.
*/
GLuint textures[] = {0};
glGenTextures(1, &textures[0]);
mTextureID = textures[0];
glBindTexture(GL_TEXTURE_2D, mTextureID);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// here is the actual problem, I get the following error on this line
// FieldView.cpp: In constructor 'game::FieldView::FieldView()':
// FieldView.cpp:89:9: error: incomplete type 'game::GameRenderer' used in nested name specifier
GameRenderer::createGlTextureFromResource(0x7f040004, mTextureID);
}
void FieldView::draw(glm::mat4 mProjMatrix, glm::mat4 mVMatrix) {
//... doesn't matter
}
}

如果我理解正确,我必须使用前向声明,并且至少不要在一个地方使用标头的包含来制动圆圈,但我不能这样做,因为我在对象之间有调用,并且没有标头编译器拒绝调用方法。编译器错误FieldView.cpp,请参阅代码中GameRenderer::createGlTextureFromResource(0x7f040004, mTextureID);调用附近的注释。

在所有这些编辑之后,问题实际上保持不变: 我在这里做错了什么?我想我在某处使用了非常糟糕的设计实践。

请原谅我最初的不准确。

我认为这应该有效:

  • 停止包含来自其他标头的标头。您不需要它们,这从它仅作为最后一行包含的事实中可以清楚地看出。作为一般规则,在标头中包含尽可能少的内容,并尽可能使用简单的声明(例如class B;)。

  • 包括A.hC.h来自C.cpp。这两个类都直接从C.cpp使用,因此您需要包含两个标头是有意义的。

至少在您发布的代码中,没有理由在A.h的底部包含B.h等等。您应该将这些包含放在实现文件中。

// A.cpp
#include "A.h"
#include "B.h"
namespace game
{
....
}

据我所知,"A.h"#include 在C.h头文件中什么也没买到。您的 C.cpp 标头应包含 A.h 和 C.h。 同样,B.h 也在尾部包括 C.h,就像以前一样,什么也买不到。

A.h - include no other headers, forward decl class C;
B.h - include no other headers, forward decl class C;
C.h - include no other headers, forward decl class A
A.cpp - include A.h, C.h
B.cpp - include A.h, B.h, C.h
C.cpp - include A.h, C.h

看来您有一个口头禅,即只包含一个.cpp文件的自定义标头。对于多类/多标头层次结构,这种情况几乎从来都不是这种情况。

你的代码为我编译。尽管通过将 C 中的构造函数更改为默认构造函数(因此 C 中的代码.cpp有一个声明)。