array of object in C++ in sfml - c++

I am trying to use vectors in sfml C++ and I am semi-failing because I am not able to create a vector consisting of 4 RectangleShapes :(
I am skipping some lines of the code which are not causing the problem
This is the code which is working but it is least optimized in my opinion
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <vector>
#include <iostream>
#include "mainCharacter.h" // it consists the mainCharacter class
class classBackground{
public:
sf::Texture texture;
sf::Sprite image;
sf::RectangleShape rectTopBorder,rectBotBorder,rectLeftBorder,rectRightBorder;
std::vector<sf::RectangleShape> rect;
classBackground(){
texture.loadFromFile("wagon.png");
image.setTexture(texture);
image.setPosition(300,250);
rectTopBorder.setSize(sf::Vector2f(230,5));
rectTopBorder.setPosition(image.getPosition());
rectTopBorder.move(0,60);
rectBotBorder.setSize(sf::Vector2f(230,5));
rectBotBorder.setPosition(image.getPosition());
rectBotBorder.move(0,225);
rectLeftBorder.setSize(sf::Vector2f(5,170));
rectLeftBorder.setPosition(image.getPosition());
rectLeftBorder.move(0,60);
rectRightBorder.setSize(sf::Vector2f(5,170));
rectRightBorder.setPosition(image.getPosition());
rectRightBorder.move(225,60);
rect.push_back(rectTopBorder);
rect.push_back(rectBotBorder);
rect.push_back(rectLeftBorder);
rect.push_back(rectRightBorder);
}
};
//in the main function
classMainCharacter mainCharacter; ///another class which has collision detection
classBackground background;
///in the loop
for(int i = 0; i<=3; i++){
mainCharacter.collision(background.rect[i]); ///colision is a function in the mainCharacter class (detects collision)
}
And this is the code which I want to work but my game is crushing :(
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <vector>
#include <iostream>
#include "mainCharacter.h" // it consists the mainCharacter class
class classBackground{
public:
sf::Texture texture;
sf::Sprite image;
std::vector<sf::RectangleShape> rect; // it doesn't work if I write rect(4) or rect = {rect1,rect2,rect3,rect3} or even rect(4)={rect1,....}
classBackground(){
texture.loadFromFile("wagon.png");
image.setTexture(texture);
image.setPosition(300,250);
rect[0].setSize(sf::Vector2f(230,5));
rect[0].setPosition(image.getPosition());
rect[0].move(0,60);
rect[1].setSize(sf::Vector2f(230,5));
rect[1].setPosition(image.getPosition());
rect[1].move(0,225);
rect[2].setSize(sf::Vector2f(5,170));
rect[2].setPosition(image.getPosition());
rect[2].move(0,60);
rect[3].setSize(sf::Vector2f(5,170));
rect[3].setPosition(image.getPosition());
rect[3].move(225,60);
}
};
//in the main function
classMainCharacter mainCharacter; ///another class which has collision detection
classBackground background;
///in the loop
for(int i = 0; i<=3; i++){
mainCharacter.collision(background.rect[i]); ///colision is a function in the mainCharacter class (detects collision)
}
what am I doing wrong? :(
I tried to defined the rects before vector and then inserting into the vector but it also doesn't work (in such way vector<...> rect = {......}).

Well even if I would not expect to much difference between the two versions, an answer is worth telling anyway as your problem has neither to do with performance nor with sfml at all but is more general.
What you try is to instantiate a class member at its declaration, what is not possible. But what you can do is either one of the following methods:
1) Use the default member initializer with the C++ 11 unified initialization syntax like so (wich may only be syntactic sugar for (2) prior to this: http://en.cppreference.com/w/cpp/language/data_members#Member_initialization):
std::vector<sf::RectangleShape> rect{4}
2) Use the initializer list in the constructor:
classBackground() : rect(4) {...}
3) Or call the resize method in the constructor:
classBackground(){
rect.resize(4);
...
}
The last one might be the worst as it first calls the standard constructor of vector<...> and changes it afterwards.

In the first version, you were successfully creating a vector of 4 elements by using push_back.
In the second version, you never allocate space for your 4 elements, so when you try and assign values to the elements of the vector, that's your crash.
If you really don't want to use push_back you can instead use resize to set the size of the vector.
Here's a simplified version of what you're trying to do
#include <vector>
class classBackground {
std::vector<int> rect;
public:
classBackground() {
rect.resize(4);
rect[0] = 1;
rect[1] = 2;
rect[2] = 3;
rect[3] = 4;
}
};
int main() {
classBackground cb;
// there, it worked.
}
Demo: http://ideone.com/YYq0oA
Alternatively if you have C++11 and your vector is always going to be 4 elements large, which in this case it seems like it might be, you should consider using std::array instead.
#include <array>
class classBackground {
std::array<int, 4> rect;
public:
classBackground() {
rect[0] = 1;
rect[1] = 2;
rect[2] = 3;
rect[3] = 4;
}
};
int main() {
classBackground cb;
// there, it worked.
}
Array works like vector in most ways, you just can't change the size, but it can potentially be more efficient.

Related

Destroying vectors of dynamic arrays via destructor in c++

I'm working on one of assignments to do with image manipulation (blending and zooming) and I've ran into a problem that I have hard time overcoming.
Structure of my application
Class Image
rgb struct: contains floats (they're flattened pixels) and overloaded operators.
pixels: a 1d array of pixels which is initialized via constructor to be h * w
Class destructor.
Destructor looks a little like this...
virtual ~Image()
{
if (pixels != NULL)
delete[] pixels;
}
Now I'm using another class called Filter which inherits from Image
class Filter: public class Image
std::vector of Image imgStack; Container for images that I'm going to blend
std::vector of Rgb pixelBuffer; A container for the pixels for each images one pixel. This is not dynamic so I'm not worried about deleting this.
Destructor for the derived class.
~Blend()
{
delete &imageStack;
}
what this part of my main.cpp looks like...
while (userInput != 5)
{
switch(userInput)
case 1:
{
Blend *meanImage = new Blend(3263, 2505, 13);
meanImage->writePPM("Mean_" + std::to_string(count) + ".ppm");//every iteration, the file name is unique
meanImage->~Blend();
}
}
In my main.cpp I'm basically running 13 images into the Blend object which stores the images in the vector container to do all my functionality on. During the run time the space used is around 1.3GB, but since my object is in a loop (i have a menu for multiple functionality) the object doesn't usually leave the scope so the destructor isn't automatically called, so I call it manually like this; medianImage->~Blend(); Now the all the error says is that my application "has triggered a breakpoint" and that's it... Note, no breakpoint is found anywhere. I'm aware that it's generally bad to use dynamic arrays because it causes all sorts of memory problems (if it's done by me), but I want to fix this just so I know how to solve these in the future.
If you have any questions of the code, I can post snippers.
Edit: here's an my Blend class.
#pragma once
#include "stdafx.h"
#include "Image.h"
#include <vector>
#include <string>
class Blend : public Image
{
private:
std::vector<Image> imageStack;
std::vector<Rgb*> pixelBuffer;//only works with pointers (no copying)
int m_noOfImages;
Rgb* getMedianFromSet();
Rgb getMeanFromSet();
Rgb getStdDev(Rgb meanPix);
public:
Blend(int width = 0, int height = 0, int noOfImages = 0):Image(width, height), m_noOfImages(noOfImages), imageStack(noOfImages), pixelBuffer(noOfImages)
{}
public:
void stack(bool push = true);
void meanBlend();
void medianBlend();
void sigmaClipping(float sigma = 0.5f);
~Blend()
{
delete &imageStack;
}
};
#pragma once
#include "stdafx.h"
#include "Image.h"
#include <vector>
#include <string>
#include <memory>
class Blend : public Image
{
private:
std::vector<Image> imageStack;
// Changed to shared_ptr<T> could use unique_ptr<T> depending on need.
std::vector<std::shared_ptr<Rgb>> pixelBuffer;//only works with pointers (no copying)
int m_noOfImages;
Rgb* getMedianFromSet();
Rgb getMeanFromSet();
Rgb getStdDev(Rgb meanPix);
public:
Blend(int width = 0, int height = 0, int noOfImages = 0):Image(width, height), m_noOfImages(noOfImages), imageStack(noOfImages), pixelBuffer(noOfImages)
{}
public:
void stack(bool push = true);
void meanBlend();
void medianBlend();
void sigmaClipping(float sigma = 0.5f);
// Clear Entire Buffer
void cleanup() {
// When using the heap with smart pointers
for ( auto item : containerVariable ) {
item.reset();
item = nullptr;
}
containerVariable.clear();
}
// Remove Single Element
void remove( unsigned idx ) {
// Write function to remove a single element from vector
}
~Blend()
{
// This is definitely wrong here: You are trying to delete a reference
// to a template container that is storing `Image` objects that
// are on the stack.
// delete &imageStack;
}
};
It is better to write a function to clean up memory, and to remove specific elements from containers when using dynamic memory than it is to use a class's destructor.

C++ Vector read access violation Mylast returned 0x8

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_() {}

Having some issues attempting to define a variable in a separate class - use to working with one.

I am trying to make a Tic-Tac-Toe game using OOP but I am having an issue. When trying to make a playing board with a total of 9 squares and all of them empty as a vector, I do the following.
Main
#include "stdafx.h"
#include <vector>
int main()
{
char empty = ' '; //Empty square on playing board
const int numbOfSquares = 9; //Total amount of squares on board
std::vector<char> board(numbOfSquares, empty); // The playing board
return 0;
}
In my board class I am trying to do the same thing but it isn't working in the same way.
Board.h
#pragma once
#include <vector>
class Board
{
private:
const char empty = ' '; //Empty square on game board
const int numbOfSquares = 9; //Number of squares on the board
std::vector<char> board(numbOfSquares, empty); //The playing board
public:
};
An error occurs in saying that 'numbOfSquares' and 'empty' is not a type name. I think I understand this error message but I am not sure on how to resolve it. Could I - overload, is that the term - the board variable in a member function instead?
I am left quite clueless on what to do and would love some help. Thank you for your time.
std::vector<char> board(numbOfSquares, empty); is not permitted when specifying the list of what your class members are. Instead you should use the constructor initializer list:
Board(): board(numbOfSquares, empty)
{
}
All members can be initialized this way. For example, your line const int numbOfSquares = 9; is a shortcut for writing:
Board(): numbOfSquares(9)
{
}
However there is no such shortcut for the case where you need to provide constructor arguments in parentheses.
There is a shortcut for providing constructor arguments as a braced initializer list, however it's wise to avoid doing this for vector as the vector will prefer to treat the contents of the braces as a list of initial values for the vector, rather than as constructor parameters.

Can you pass a subclass as an argument to a function with a superclass parameter? C++

I'm building a little C++ game (with SFML, but that's irrelevant for the most part), and I'm changing some code around to make it more reusable. I want to make a method that shifts a bunch of shapes that are stored in an array.
Let's say we have a class called Shape, and another, its subclass, called Rectangle. I want the function to work for any shape. Is this possible? I thought I could do something like what you see below, but it crashes the game unless I change the first parameter to take an array of Rectangles.
void shift_shapes(Shape *shapes, int num_shapes, int x_offset, int y_offset)
{
for (int i = 0; i < num_shapes; i++)
shapes[i].move(x_offset, y_offset);
}
Rectangle rects[100];
// *Add 100 rectangles*
shift_shapes(rects, 100, 10, 5);
Thanks for the help!
Array does not hold polimorphism, you could archive this by using vector of pointers and pass the reference to the vector into the function. Something like:
#include <memory>
#include <vector>
void shift_shapes(std::vector<std::unique_ptr<Shape> >& shapes, int num_shapes, int x_offset, int y_offset)
{
for (int i = 0; i < num_shapes; i++)
{
shapes[i].move(x_offset, y_offset);
}
}

Adding elements to a vector inside a c++ class not being stored

Edit: My debugger was lying to me. This is all irrelevant
Howdy all,
I had a peek at Adding element to vector, but it's not helpful for my case.
I'm trying to add an element (custom class LatLng) to another object (Cluster) from a third object (ClusterManager).
When I pass my LatLng to Cluster (last line of ClusterManager.cpp), and jump into Cluster::addLocation, at the end of the function execution gdb says my new LatLng has been added to Cluster, but the moment I jump back into the scope of the highest class, ClusterManager, the new LatLng added to the vector 'locStore' is not present in either runtime or debug.
Any ideas?
DJS.
DE: Xcode 3.2 (Targeted to Debug 10.5)
OS: OSX 10.6
Compiler: GCC 4.2
Arch: x86_64
ClusterManager.cpp (where it's all being called from):
void ClusterManager::assignPointsToNearestCluster()
{
//Iterate through the points.
for (int i = 0; i < locationStore.size(); i++)
{
double closestClusterDistance = 100.1;
// Make sure to chuck the shits if we don't find a cluster.
int closestCluster = -1;
int numClusters = clusterStore.size();
// Iterate through the clusters.
for (int j = 0; j < numClusters; j++) {
double thisDistance = locationStore[i].getDistanceToPoint( *(clusterStore[j].getCentroid()) );
// If there's a closer cluster, make note of it.
if (thisDistance < closestClusterDistance) {
closestClusterDistance = thisDistance;
closestCluster = j;
}
}
// Remember the penultiment closest cluster.
this->clusterStore[closestCluster].addLocation( this->locationStore[i] );
}
}
ClusterManager.h
#include "Cluster.h"
#include "LatLng.h"
#include <vector>
class ClusterManager{
private:
std::vector<Cluster> clusterStore;
std::vector<LatLng> locationStore;
public:
ClusterManager();
void assignPointsToNearestCluster();
void addLocation(int,double,double);
};
Cluster.h:
#include <vector>
#include <string>
#include "LatLng.h"
class Cluster {
private:
std::vector<LatLng> locStore;
LatLng newCentroid;
bool lockCentroid;
int clusterSize;
int clusterID;
public:
Cluster(int,LatLng&);
void addLocation(LatLng&);
LatLng* getCentroid();
};
Cluster.cpp
Cluster::Cluster(int newId, LatLng &startPoint)
{
this->clusterID = newId;
this->newCentroid = startPoint;
};
void Cluster::addLocation(LatLng &newLocation)
{
(this->locStore).push_back( newLocation );
};
LatLng* Cluster::getCentroid()
{
return &newCentroid;
};
The debugger is possibly lying. I've found Xcode has issues has viewing the contents of vectors, try using some asserts to make sure the vector in question is actually being filled.
What does your copy constructor for the class LatLng look like? When you call std::vector::push_back(), a copy of the argument is made before adding it to the vector. The lack of a non-compiler-generated copy constructor may indicate why you are not seeing certain values in the target vector.
Also, you mention that you are getting an out-of-bounds error when iterating the contents of the vector. This suggests that there are fewer elements in the vector than you expected there to be. Consider iterating through the vector using a for-loop, bound by vector.size().
What does the copy constructor of LatLng do? This determines what actually winds up in the vector when you call push_back.
btw it's a bit more efficient to use iterators rather than indices in your vector loops - less operator[] usage, in favour of direct refs to vector members via the iterator.
std::vector::push_back() expects a const reference as input, but you are passing it a non-const reference instead, so the compiler has to create a temporary LatLng object, which is what gets added to the vector instead of your original LatLng object.