Круговая головная боль зависимости

Первоначальный вопрос был
У меня три класса A, B а также C, A имеет ссылку и звонки на B, который имеет ссылку и звонки на C, Но C есть вызов A статический метод. И я просто не могу заставить этот статический вызов работать.

Но ребята убедили меня в некоторой неточности в усечении кода, поэтому настоящие имена классов GameRenderer, GameView а также FieldView, GameRenderer имеет ссылку и звонки на 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

GameView.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); вызов.

После всех этих правок вопросы на самом деле остаются прежними:
Что я здесь не так делаю? Я предполагаю, что я использую очень плохую практику проектирования где-то.

Пожалуйста, прости мою первоначальную неточность.

0

Решение

Я думаю, что это должно работать:

  • Прекратите включать заголовки из других заголовков. Они вам не нужны, что видно из того факта, что они включены только в качестве последней строки. Как правило, включайте как можно меньше в заголовки и старайтесь избегать простых объявлений (таких как class B;) когда возможно.

  • Включите оба A.h а также C.h от C.cpp, Оба класса используются непосредственно из C.cppпоэтому имеет смысл включать оба заголовка.

4

Другие решения

Нет причин, по крайней мере, в коде, который вы разместили, чтобы включить B.h на дне A.h и так далее. Вы должны поместить эти включения в файлы реализации.

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

Из того, что я могу сказать, #include «A.h» ничего не покупает в заголовочном файле 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. Это почти никогда не имеет место с иерархиями с несколькими классами / с несколькими заголовками.

1

Ваш код компилируется для меня. Хотя можно изменить конструктор в C на конструктор по умолчанию (поэтому код в C.cpp имеет объявление).

0
По вопросам рекламы [email protected]