Reputation: 1569
The initial question was
I have three classes A
, B
and C
. A
has a link and calls to B
, which has a link and calls to C
. But C
has a call to A
static method. And I just can't get this static call to work.
But guys cought me on some inaccuracy in truncating the code, so the real names of the classes are GameRenderer
, GameView
and FieldView
. GameRenderer
has a link and calls to GameView
, which has a link and calls to FieldView
. But FieldView
has a call to GameRenderer
static method createGlTextureFromResource
. And I just can't get this static call to work.
Here is the full and real headers 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
here is cut version of 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
}
}
If I understand right, I have to use forward declarations and don't use includes of headers at least in one place to brake the circle, but I can't do this because I have calls between objects, and without headers compiler refuses to do calls to methods. The compiler error is in the FieldView.cpp
, see comments in the code near the GameRenderer::createGlTextureFromResource(0x7f040004, mTextureID);
call.
After all these edits questions actually stays the same: What am I doing wrong here? I suppose I'm using very bad design practice somewhere.
Please forgive my initial inaccuracy.
Upvotes: 0
Views: 479
Reputation: 28362
Your code compiles for me. Albeit by changing your constructor in C to be a default constructor (so the code in C.cpp has a declaration).
Upvotes: 0
Reputation: 66244
From what I can tell the #include "A.h" is buying you nothing in the C.h header file. Your C.cpp header should include A.h and C.h. Likewise, the B.h is including C.h at the tail as well, and just like before, buys you nothing.
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
It appears you have a mantra of only including one custom-header for a .cpp file. This is almost never the case with multi-class/multi-header hierarchies.
Upvotes: 1
Reputation: 182008
I think this should work:
Stop including headers from other headers. You don't need them, which is clear from the fact that it's only included as the last line. As a general rule, include as little as possible in headers and try to get away with simple declarations (such as class B;
) whenever possible.
Include both A.h
and C.h
from C.cpp
. Both classes are used directly from C.cpp
, therefore it makes sense that you need to include both headers.
Upvotes: 5
Reputation: 227518
There is no reason, at least in the code you posted, to include B.h
at the bottom of A.h
and so on. You should put these includes in the implementation files.
// A.cpp
#include "A.h"
#include "B.h"
namespace game
{
....
}
Upvotes: 4