I am trying to build a window controller for SDL with its own pseudo-pixels. I had the code working using a single big and ugly translation unit, but am now trying to refactor the same code into multiple units and classes.
In this class, I am attempting to define the controller for the window, and I am having trouble understanding how to work with a nested structure inside a class.
The errors I am getting are on the line Pixel* pixels[][];. The compiler complains that "incomplete type is not allowed". The struct seems to be fully defined in the .cpp.
The second error is that "an array may not have elements of this type"; I understand that the second dimension of an array has to be of a defined size, but how do I define this size at compile-time while keeping my code flexible for windows of different sizes?
//PxWindow.h
#include <SDL.h>
class PxWindow {
struct Pixel {
static int PARENT_PIXEL_SIZE;
// Data members
int x, y;
Color color;
// Methods
int screenX();
int screenY();
SDL_Rect getPixelRect();
};
// Private Data Member declarations
private:
int PIXEL_SIZE;
int NUM_PIXELS_X;
int NUM_PIXELS_Y;
// Public Data Member declarations
public:
Pixel* pixels[][];
SDL_Rect rects[][];
public:
PxWindow(int,int,int);
int getPixelSize();
int getNumX();
int getNumY();
};
// PxWindow.cpp
#include "PxWindow.h"
/*
* Pixel Structure method definitions
*/
SDL_Rect PxWindow::Pixel::getPixelRect() {
return SDL_Rect{ screenX(), screenY(), PARENT_PIXEL_SIZE, PARENT_PIXEL_SIZE };
};
int PxWindow::Pixel::screenX() { return x * PARENT_PIXEL_SIZE; }
int PxWindow::Pixel::screenY() { return y * PARENT_PIXEL_SIZE; }
/*
* PxWindow Class method definitions
*/
PxWindow::PxWindow(int px_size, int num_x, int num_y) :
PIXEL_SIZE(px_size),
NUM_PIXELS_X(num_x),
NUM_PIXELS_Y(num_y) {
Pixel::PARENT_PIXEL_SIZE = PIXEL_SIZE;
};
int PxWindow::getPixelSize() {
return PIXEL_SIZE;
};
int PxWindow::getNumX() {
return NUM_PIXELS_X;
};
int PxWindow::getNumY() {
return NUM_PIXELS_Y;
};
For the first error:
You should check your includes. Most likely one is missing to complete your struct "Pixel". You seem to use SDL_Rect, but I can't see the include for SDL in your header file.
For your second error:
To make the array a little more dynamic you would have to create a new array (arrayTwo) of array.size() + 1 and copy all data from array to arrayTwo yourself.
You could also use a (or two nested vectors for 2d), but it depends on your performance needs.
Related
I really need help on this one cause I am extremely stuck and have no idea what to do.
Edit:
A lot of you guys are saying that I need to use the debugger but let me be clear I have not used C++ for an extremely long time and I've used visual studio for a grand total of 2 weeks so I do not know all the cool stuff it can do with the debugger.
I am a student at university at the beginning of my second year who is trying to work out how to do something mostly by failing.
I AM NOT a professional coder and I don't have all the knowledge that you people have when it comes to these issues and that is why I am asking this question. I am trying my best to show my issue so yes my code contains a lot of errors as I only have a very basic understanding of a lot of C++ principles so can you please keep that in mind when commenting
I'm only posting this here because I can don't know who else to ask right now.
I have a function called world that is suppose to call my render class to draw all the objects inside of its vector to the screen.
#include "C_World.h"
C_World::C_World()
{
// creates an instance of the renderer class to render any drawable objects
C_Renderer *render = new C_Renderer;
}
C_World::~C_World()
{
delete[] render;
}
// adds an object to the world vector
void C_World::addToWorld(C_renderable* a)
{
world_list.push_back(a);
}
void C_World::World_Update()
{
render->ClearScreen();
World_Render();
}
void C_World::World_Render() {
for (int i = 0; i < 1; i++)
{
//render->DrawSprite(world_list[i]->getTexture(), world_list[i]->get_X, world_list[i]->get_Y());
render->DrawSprite(1, 1, 1);
}
}
While testing I commented out the Sprites get functions in order to check if they were causing the issue.
the renderer sprites are added to the vector list in the constructor through the create sprite function
C_Renderer::C_Renderer()
{
// test sprite: Id = 1
CreateSprite("WhiteBlock.png", 250, 250, 1);
}
I thought this might of been the issue so I had it in other functions but this didn't solve anything
Here are the Draw and create Sprite functions
// Creates a sprite that is stored in the SpriteList
// Sprites in the spriteList can be used in the drawSprite function
void C_Renderer::CreateSprite(std::string texture_name,
unsigned int Texture_Width, unsigned int Texture_height, int spriteId)
{
C_Sprite *a = new C_Sprite(texture_name,Texture_Width,
Texture_height,spriteId);
SpriteList.push_back(a);
size_t b = SpriteList.size();
HAPI.DebugText(std::to_string(b));
}
// Draws a sprite to the X and Y co-ordinates
void C_Renderer::DrawSprite(int id,int x,int y)
{
Blit(screen, _screenWidth, SpriteList[id]->get_Texture(),
SpriteList[id]->getTexture_W(), SpriteList[id]->getTexture_H(), x, y);
}
I even added some test code into the create sprite function to check to see if the sprite was being added too the vector list. It returns 1 so I assume it is.
Exception thrown: read access violation.
std::_Vector_alloc<std::_Vec_base_types<C_Sprite *,
std::allocator<C_Sprite *> > >::_Mylast(...) returned 0x8.
that is the full error that I get from the compiler
I'm really really stuck if there is anymore information you need just say and ill post it straight away
Edit 2:
#pragma once
#include <HAPI_lib.h>
#include <vector>
#include <iostream>
#include "C_renderable.h"
#include "C_Renderer.h"
class C_World
{
public:
C_World();
~C_World();
C_Renderer *render = nullptr;
void World_Update();
void addToWorld(C_renderable* a);
private:
std::vector<C_renderable*> world_list;
void C_World::World_Render();
};
#pragma once
#include <HAPI_lib.h>
#include "C_renderable.h"
#include "C_Sprite.h"
#include <vector>
class C_Renderer
{
public:
C_Renderer();
~C_Renderer();
// gets a pointer to the top left of screen
BYTE *screen = HAPI.GetScreenPointer();
void Blit(BYTE *destination, unsigned int destWidth,
BYTE *source, unsigned int sourceWidth, unsigned int sourceHeight,
int posX, int posY);
void C_Renderer::BlitBackground(BYTE *destination,
unsigned int destWidth, unsigned int destHeight, BYTE *source,
unsigned int sourceWidth, unsigned int sourceHeight);
void SetPixel(unsigned int x,
unsigned int y, HAPI_TColour col,BYTE *screen, unsigned int width);
unsigned int _screenWidth = 1750;
void CreateSprite(std::string texture_name,
unsigned int Texture_Width,unsigned int Texture_height, int spriteId);
void DrawSprite(int id, int x, int y);
void ClearScreen();
private:
std::vector<C_Sprite*> SpriteList;
};
I don't say this lightly, but the code you've shown is absolutely terrible. You need to stop and go back several levels in your understanding of C++.
In all likeliness, your crash is the result of a simple "shadowing" issue in one or more of your functions:
C_World::C_World()
{
// creates an instance of the renderer class to render any drawable objects
C_Renderer *render = new C_Renderer;
}
C_World::~C_World()
{
delete[] render;
}
There are multiple things wrong here, and you don't show the definition of C_World but if this code compiles we can deduce that it has a member render, and you have fallen into a common trap.
C_Renderer *render = new C_Renderer;
Because this line starts with a type this is a definition of a new, local variable, render. Your compiler should be warning you that this shadows the class-scope variable of the same name.
What these lines of code
C_World::C_World()
{
// creates an instance of the renderer class to render any drawable objects
C_Renderer *render = new C_Renderer;
}
do is:
. assign an undefined value to `this->render`,
. create a *local* variable `render`,
. construct a dynamic `C_Renderer` presumably on the heap,
. assign that to the *local* variable `render`,
. exit the function discarding the value of `render`.
So at this point the memory is no-longer being tracked, it has been leaked, and this->render is pointing to an undefined value.
You repeat this problem in several of your functions, assigning new results to local variables and doing nothing with them. It may not be this specific instance of the issue that's causing the problem.
Your next problem is a mismatch of new/delete vs new[]/delete[]:
C_World::~C_World()
{
delete[] render;
}
this would result in undefined behavior: this->render is undefined, and delete[] on a non-new[] allocation is undefined.
Most programmers use a naming convention that distinguishes a member variable from a local variable. Two common practices are an m_ prefix or an _ suffix for members, e.g.
class C_World
{
public:
C_Foo* m_foo; // option a
C_Renderer* render_; // option b
// ...
}
Perhaps you should consider using modern C++'s concept of smart pointers:
#include <memory>
class C_World {
// ...
std::unique_ptr<C_Renderer> render_;
// ...
};
C_World::C_World()
: render_(new C_Renderer) // initializer list
{}
But it's unclear why you are using a dynamic allocation here in the first place. It seems like an instance member would be better:
class C_World {
C_Renderer render_;
};
C_World::C_World() : render_() {}
So I am trying to make snake clone.
I have made a BodyPiece class which has certain variables I would like to be const, as they should not change. This was not a problem when I simply created an instance of Bodypiece to test out. However I want to be able to add pieces as the snake grows so I made a vector body variable. As you can see from the code below:
In BodyPiece.h:
#pragma once
#include "D3DGraphics.h"
#include "Keyboard.h"
#include "Direction.h"
class BodyPiece
{
public:
BodyPiece(int xPos, int yPos, Direction* dir);
~BodyPiece();
void Draw(D3DGraphics& gfx);
void UpdateDirection(KeyboardClient& kbd);
void Move();
private:
Direction* dir;
int xPos;
int yPos;
int width = 5;
int height = 5;
int vx = 5;
int vy = 5;
};
In Game.h file
BodyPiece vector body declared:
std::vector<BodyPiece> body;
In Game.cpp file
vector initialised in initialiser list.
body({ {400, 300, &d } })
If I make any variables in BodyPiece const, it will generate an error:
error C2582 'operator=' function is unavailable in class BodyPiece.
My questions here are:
What causes that? I have looked online and have a little bit of an idea but it really is only a little bit.
How can I have const variables, use a vector container(or another type of container if that will help, does not have to be vector) and keep the compiler happy? Or should I just completely change my approach?
Thank you in advance.
The problem is that if you don't have an assignment operator, then the compiler will generate one for you, that does simple shallow copying of the members. However, if you have actual const member variables (and not only default-initialized like yours) then those can't be copied and the compiler can't create an assignment operator.
The simple solution is to make the constants actual constants and also static so they are members of the class and not part of a single object:
class BodyPiece
{
...
static int const width = 5;
static int const height = 5;
};
The only drawback with this is that you need to actually define these member variables, in a single source file:
int const BodyPiece::width;
int const BodyPiece::height;
The other solution is to explicitly create an assignment operator that copies the data needed:
class BodyPiece
{
public:
...
BodyPiece& operator=(BodyPiece const& other)
{
// Copy data from other to this
xPos = other.xPos;
...
return *this;
}
...
};
I'm having some trouble using header files.
I would like to "refresh" a .h file, in order to update all the values of the constants in it which depend on an extern variable (defined in the main .cc file).
This is approximately the situation:
Header file (header.h)
extern int extern_value;
const int one = value;
const int two = value * 2;
const int three = value * 3;
Main program
#include "header.h"
int extern_value;
int main(){
extern_value = 10;
// Here is where I would like to refresh the header file.
// Here is where I would like to have my dependant constants
// (one, two and three) being updated.
return 0;
}
Please consider that this is an extreme approximation of the problem.
Do you guys have any idea about how to solve it?
Thanks in advance.
EDIT:
This is my actual problem:
I would like to have a header file which contains all the graphical constants that my project needs. They ALL depend on the size of the display. The first thing that the main program does is getting information about the display size; THEN, I would like the program to "export" this information on the header file, so it can calculate all the graphical constants relatively to the size of the display.
You can't do this. For a variety of reasons, but not least because your variables are const, and the expression you use to compute a value to be assigned to them is not continually re-evaluated.
What you want is to use functions:
extern int extern_value;
int one() { return extern_value; }
int two() { return extern_value * 2; }
int three() { return extern_value * 3; }
Other notes:
You probably shouldn't have an extern variable for this. Pass value to the function instead:
int one(const int value) { return value; }
int two(const int value) { return 2 * value; }
int three(const int value) { return 3 * value; }
int main() {
int value = 10;
std::cout << one(value) << " " << two(value) << "\n";
return 0;
}
You can't "refresh" a header file. The content of the file is what you typed, and this is included (effectively, pasted into) the source file when you use #include "my_header.h". You can update the value associated with non-const variables, but if you want to repeatedly evaluate an expression with different values, the best way is to turn that expression into a function as shown above, and call the function with different parameters.
You'll probably need to either move the function definitions from the header to a source file, or mark them as inline, otherwise you may be warned (or receive errors) about multiple definitions if you use the same header in multiple source files.
To address your actual problem, if you need to expose information through extern variables, you'll need to make them non-const, and have your main() function initialise them, or do so during static initialisation. There are a number of issues to be aware of when doing this, so it's much safer to provide functions that compute the geometry accordingly, and base those computations on one or two function arguments, or a small number of extern variables that are statically initialised to something safe, then set appropriately once the information becomes available. Further details can be obtained by searching for e.g. static initialisation or extern variables.
In this case, you may wish to consider creating a class to hold your geometry and perform the relevant computations. A pointer to an instance of this class can be created as an extern variable, and initialised on program initialisation (i.e. statically). You can then provide the derived "constants" as member functions which calculate their result based on a small number of encapsulated values, which can be set / updated if necessary. You can even make it such that these are const, if you're careful.
See, for instance the example below (live demo):
// ******** HEADER FILE ********
class Geometry {
public:
Geometry(const int rows, const int cols)
: rows_(rows), cols_(cols) {}
int rows() const { return rows_; }
int cols() const { return cols_; }
int pixels() const { return rows_ * cols_; }
// whatever other "constants" you need, defined as functions
// containing expressions based on rows_ and cols_.
private:
// Make copy constructor & assignment operator private to prevent copying
Geometry(const Geometry&);
Geometry& operator=(const Geometry&);
// The data from which everything else is calculated
const int rows_;
const int cols_;
};
extern const Geometry* the_geometry;
// ******** SOURCE FILE ********
#include <iostream>
int main() {
const int rows = 80; // or however you get the number of rows
const int columns = 25; // or however you get the number of columns
the_geometry = new Geometry(rows, columns);
std::cout << the_geometry->pixels() << "\n";
return 0;
}
const Geometry* the_geometry = nullptr;
I've created a structure in a header file as follows:
typedef struct
{
GLfloat lgtR, lgtG, lgtB, lgtA;
GLfloat x, y, z;
bool islight;
GLfloat width, height, depth;
GLenum lightn;
particle prt;
int maxprt;
} emitter;
which works without a problem.
However, in that particular header file, I want to declare a global emitter that I can use in all the functions and isn't part of the main source file:
// header.h global declaration
emmiter currentEmit;
GLvoid glSetEmitter(emitter emitter)
{
currentEmit = emitter;
}
However, when I do try this, I get a whole lot of "error C2228: left of '.variable' must have class/struct/union, so I'm assuming it's not declaring my structure here at all.
Is there a way to declare that structure globally within a header file, and if so, is there also a way to keep it from being part of the other .cpp files as well?
emitter is not the same as emmiter.
Also, since this is C++ - just write struct {}; directly, there's no need for a typedef.
Your whole header is wrong, and will give multiple definitions if included in multiple translation units:
// header.h global declaration
extern emitter currentEmit; // <-- note extern
inline GLvoid glSetEmitter(emitter emitter) // <-- note inline
{
currentEmit = emitter;
}
currentEmit needs to be defined in a single implementation file, not a header. The function needs to be inline so it's not defined by all TU.
Last thing: pass the parameter by const reference:
inline GLvoid glSetEmitter(const emitter& emitter) // <-- note inline
{
currentEmit = emitter;
}
Otherwise an unnecessary copy will be created.
typedef struct
{
GLfloat lgtR, lgtG, lgtB, lgtA;
GLfloat x, y, z;
bool islight;
GLfloat width, height, depth;
GLenum lightn;
particle prt;
int maxprt;
} emitter;
should better be
struct Emitter
{
GLfloat lgtR, lgtG, lgtB, lgtA;
GLfloat x, y, z;
bool islight;
GLfloat width, height, depth;
GLenum lightn;
particle prt;
int maxprt;
};
Is there a way to declare that structure globally within a header file,
Yes, there are two main ways to avoid the variable being created in each compilation unit.
First there is the Meyers' singleton:
namespace g {
inline Emitter& emitter()
{
static Emitter theEmitter;
return theEmitter;
}
}
void foo() { g::emitter().x = 666; }
Then there is the templatization trick:
namespace detail {
template< class Dummy >
struct EmitterVariable
{
static Emitter v;
};
template< class Dummy >
Emitter EmitterVariable<Dummy>::v = {};
}
namespace g {
static Emitter& emitter = EmitterVariable<void>::v;
}
void foo{ g::emitter.x = 666; }
and if so, is there also a way to keep it from being part of the other .cpp files as well?
Yes, both of the above solutions do that.
The last one, however, injects a reference into each compilation unit, which in practice will be the size of a pointer.
That said, global variables tend to give very messy data flows. You don't know which part of the code put something there. You don't know if or when it's properly initialized. You don't know which other parts will be affected if you change data here. Or when. And so on. So it's absolutely not a good idea. Global constants, OK, but global variables, Just Say No™.
Hi i am trying to understand how to use the 'this' pointer. Now i wrote a sample program which uses a class Image which is a subclass of a class BMP. Now the functions TellWidth and TellHeight are declared in the BMP class. Now the compiler gives me an error which says that the TellWidth function does not exist in Image. But as Image is a subclass of BMP shouldnt it inherit the functions in BMP.
How do i resolve this
void Image :: invertcolors()
{
int x;
int y;
int width =(*this).TellWidth();
int height = (*this)->TellHeight();
for(x=0,x<=height-1;x++){
for(y=0,y<=width-1;y++){
(*this)(x,y)->Red = (255 - (*this)(x,y)->Red);
(*this)(x,y)->Blue = (255 - (*this)(x,y)->Blue);
(*this)(x,y)->Green = (255 - (*this)(x,y)->Green);
}
}
delete width;
delete height;
}
Image
class Image : public BMP
{
public:
void invertcolors();
void flipleft();
void adjustbrightness(int r, int g, int b) ;
};
This class is too big to post here, here is a relavent excerpt
class BMP {
private:
int Width;
int Height;
public:
int TellBitDepth(void) const;
int TellWidth(void) const;
int TellHeight(void) const;
};
TellWidth() is most likely declared as private (or has no accessor modifier) in the BMP class. It needs to be protected or public for the Image class to be able to access it, and it needs to be also virtual, if you want to be able to override it in the Image class.
And the proper this usage is like this:
int width = this->TellWidth();
int height = this->TellHeight();
Read this for a quick tutorial on this.
One point about this: you rarely need to mention it explicitly. The usual exception is when you need to pass it into a non-member function (which doesn't seem to be the case here.)
When you're inside of a class member function, this->field can be accessed simply as field, and this->function(x) can be invoked as function(x).
Here are some comments on your code. I hope they're helpful.
void Image :: invertcolors()
{
// Don't define these here; that's old C-style code. Declare them where
// they're needed (in the loop: for (int x=0...)
int x;
int y;
// Change the lines below to
// int width = TellWidth();
// int height = TellHeight();
// (*this).TellWidth() should work, but is redundant;
// (*this)->TellHeight() should probably *not* work, as once you've
// dereferenced *this, you're dealing with an object instance, not a
// pointer. (There are ways to make (*this)->that() do something useful,
// but you're probably not trying something like that.)
int width =(*this).TellWidth();
int height = (*this)->TellHeight();
for(x=0,x<=height-1;x++){
for(y=0,y<=width-1;y++){
// After locating the BMP class through google (see Edit 2),
// I've confirmed that (*this)(x,y) is invoking a (int,int) operator
// on the BMP class. It wasn't obvious that this operator
// was defined; it would have been helpful if you'd posted
// that part of the header file.
(*this)(x,y)->Red = (255 - (*this)(x,y)->Red);
(*this)(x,y)->Blue = (255 - (*this)(x,y)->Blue);
(*this)(x,y)->Green = (255 - (*this)(x,y)->Green);
}
}
// These are int values. They can't be deleted, nor do they need to be.
// I'm sure the compiler has told you the same thing, though perhaps not
// in the same way.
delete width;
delete height;
}
EDIT: Looks like there's someone else taking the same course as the OP. The example presented there makes it clearer that Image is supposed to have some sort of array accessor, which may explain what (*this)(x,y)->Red = (255 - (*this)(x,y)->Red) was intended to achieve.
EDIT 2: Here's the source for the original BMP class.
class Image is defined as
class Image : public BMP
{
public:
void invertcolors();
void flipleft();
void adjustbrightness(int r, int g, int b) ;
};