Reference to non static member function must be called - c++

I have a vector bars that contains several coloured box objects.Each box object has it's own draw and update function. Each box moves from one side of the screen to the next side. when it's outside the screen the box should be removed. I'm using iterators to move the boxes and determine when they are outside of the screen.
I'm very new to c++ and I'm having trouble getting the code to work. the function to erase an object from a vector is giving me the error Reference to non static member function must be called. I'm reading up on static and non static members but I'm still a bit lost.
here's my main header file with the relevant code
class game : public ofxiPhoneApp {
public:
void setup();
void update();
void draw();
void exit();
vector <Colorbar> bars;
bool checkBounds (Colorbar &b);
};
in my game.mm file I create the vector and iterate over it to set the properties of the coloured bar objects:
void game::setup(){
bars.assign(5, Colorbar());
for (int i = 0; i<bars.size(); i++) {
ofColor color = colors.giveColor();
bars[i].setup();
bars[i].setColor(color.r,color.g,color.b);
bars[i].setWidth(50);
bars[i].setPos(ofGetScreenHeight()-(i*50), 0);
}
}
the update function that move the bars across the screen.
void game::update(){
for(vector<Colorbar>::iterator b = bars.begin(); b != bars.end(); b++){
(*b).update();
}
//this is the part that gives the error
bars.erase((remove_if(bars.begin(), bars.end(), checkBounds),bars.end()));
}
and here's the function to check if the box is out of bounds
bool game::checkBounds (Colorbar &b){
if (b.pos.x > ofGetScreenHeight()+50) {
// do stuff with bars vector here like adding a new object
return true;
} else {
return false;
}
}
I've done some experimenting, and making the bool checkBounds (Colorbar &b);
non-static by removing it from the header file makes the code work. but the problem is that I'd also like to be able to access the bars vector in that function to add a new object when an old one is deleted. And that won't work anymore.
How can I solve this?

You need a unary functor taking a ColourBar. A member function has an implicit first parameter for this. This means it cannot be called like this:
Colorbar cb;
game::checkBounds(cb);
It needs to be bound to an instance of its class, otherwise it would not be able to access other members of that instance. So you need to bind the checkBounds member function to an instance of game. In your case, this looks like the right instance to bind:
#include <functional> // for std::bind
using std::placeholders; // for _1
...
remove_if(bars.begin(), bars.end(), std::bind(&game::checkBounds, this, _1)) ...

Related

How can an object of a vector access the vector elements

This is a program that simulates a simple resource gathering game
The robots gather resources from the map and move around randomly each one doing some actions.
My problem is that i want to access a vector from class map within the derivered class of robots "RescueBot" .
The program is written in multiple files, header.h , header.cpp, main.cpp
I have a vector of objects type "Robots" and an example of my header.h file:
class Map{
private:
char World[20][20]; // The size of Map is 20 x 20
vector<Robots*>RobotsVector;
public:
Map();
vector<Robots*>*getRobotsVector();
}
// I access the vector with getRobotsVector() which belongs to Map class but returns
// Robot objects. Done this so i can access Robot objects within the Map class.
class Robots
{
private:
//some variables
public:
//some functions
virtual void movement()=0; // this is the function that handles the robots moves
virtual void action()=0; // this is the function that handles the robots actions
}
class RescueBot:public Robots{
void movement();
void action();
//some unique RescueBot stuff here
}
This is from the header.cpp file:
#include "header.h"
vector<Robots*>*Map::getRobotsVector(){return &RobotsVector;}
//example of object creation and pushing into vector
void Map::creation(){
for (int x=0;x<4;x++){
getRobotsVector()->push_back(new RescueBot);
}
}
void RescueBot::action(){
//do stuff
for(int i=0;i<Map::getRobotsVector()->size();i++){
//Here is the problem. I cant get inside the for loop
Map::getRobotsVector()->at(i)->setDamaged(false); //Changes a flag in other objects
}
}
I Have tried making the Robots class derivered class of Map. After that when i run it the vector i access in RescueBot::action is empty, while the actual vector has objects in it.
If i dont make it derivered it doesnt compile.
How can i access the vector from within the RescueBot::action() ??
The problem is that you have no Map instances.
The way you're calling it currently would only work if the getRobotsVector method were static, but you don't want that.
The reason it works when you make the Robots class a derived class of Map is because Map::getRobotsVector() would just mean you want to invoke the getRobotsVector method on the instance that the RescueBot::action function is operating on.
The solution is to pass an instance of a Map to your action functions by reference.
This is what your action function would look like then:
void RescueBot::action(Map& map) {
// Do whatever you want with the map here.
// For example:
map.getRobotsVector()->at(i)->setDamaged(false);
}

Passing a class Member function as an Argument

I have a class as follows and a main method as follows:
class Mesh
{
public:
void draw()
void draw(){}
}
int main(int argc,char* argv[])
{
Mesh mesh;
glutDisplayFunc(mesh.draw);
}
So I want to pass a member function of an object as argument, but the compiler displays the following error message:
error: argument of type ‘void (Mesh::)()’ does not match ‘void (*)()’
What am I doing wrong?
Since draw is a non-static member function, it needs an instance of the class to operate upon.
In pure C++, you would use a function object (a.k.a. "functor", see std::function or its predecessor boost::function). That's sadly not an option in C or C APIs.
In this case, since there's no data that is handed to the callback, you must make some sort of static function (either class static or file static) that does the right thing when it is called.
If you only ever have one Mesh, then it's easy: either make everything in the class static (in which case it's basically a namespace), or have a non-member function that calls draw against the one instance of your Mesh:
// at some global-ish file scope...
// we define our class
class Mesh { ... };
// and here's the one global instance of it
Mesh myOneMesh;
// and here is our global / static function that "knows"
// which instance to draw
void drawMyOneMesh() { myOneMesh.draw(); }
// then, in the main flow of your program:
glutDisplayFunc( &drawMyOneMesh );
If you have multiple meshes, it looks like the best you can do is to key it off of the current window. Without knowing much about your app or about the GLUT API, I would probably do something like this to enable a mesh-per-window callback:
#include <map>
// this could also be a class with all-static members, if one
// were so inclined. might be worth it, if only to protect 'map'
// from external meddling.
namespace WindowToMesh
{
typedef std::map< int, Mesh * > Map;
Map map;
void addMapping( int win, Mesh * mesh )
{
map.insert( { win, mesh } );
}
void removeMapping( int win )
{
map.erase( win );
}
void draw()
{
int win = glutGetWindow();
Map::iterator it = map.find( win );
if ( it != map.end() )
it.second->draw();
}
} // end namespace WindowToMesh
Now, in your main program, you can associate a new Mesh with the current window:
Mesh * m = new Mesh( ... );
WindowToMesh::addMapping( glutGetWindow(), m );
And you can associate the (effectively static) WindowToMesh::draw function as the callback:
glutDisplayFunc( &WindowToMesh::draw );
When you're ready to destroy the Mesh, make sure you're in the same window, and then:
WindowToMesh::removeMapping( glutGetWindow() );
Depending on other factors, it might make sense to do a bidirectional mapping (so you can find things by Mesh * and not just by window int, or to do a brute-force scan on the rare unregistration, etc.
I don't have an environment in which I can test that, but it should be close. Good luck!
The problem is that a member function pointer needs some information to be called, i.e. the instance to be called on, which will then be accessible by the this pointer within the implementation of the member function, so you can access member variables. I think you want to do this, since your design looks like you want to draw stuff which is defined in Mesh.
There are possibilities to turn a member function pointer into a "normal" function pointer. But you have to keep in mind that this piece of information (the instance of Mesh) has to be available once this function is called. This means that a typical transformation from a member function pointer to a "normal" function pointer adds a parameter (the instance).
But glutDisplayFunc() accepts a void(*)(void) function pointer, i.e. an empty parameter list, so it won't tell the called function anything. You have to make sure that once the passed function is called, you can howsoever reconstruct the "context", i.e. the Mesh instance.
This can be done by pointing to a Mesh instance from a global point in your code. It will always be used when you call the helper function we are about to write. So when you pass a pointer to glutDisplayFunc() our helper function knows which Mesh to use, once we told it which it should use.
class Mesh
{
public:
void draw() { ... }
}
Mesh *instance;
// Helper function called by glut:
void display() {
// Now we can access a particular instance:
instance->draw();
}
int main(int argc,char* argv[])
{
Mesh mesh;
// First point to this instance globally:
instance = &mesh;
// Then, pass our helper function which now has an empty parameter list:
glutDisplayFunc(&display);
}
This solution has a restriction. You can't reuse the same function pointer with different instances. So you can't turn any instance into a function pointer, but only one for each globally defined instance pointer. But since you just want to pass your draw function to glutDisplayFunc, you only need to do this once, so it should be fine. I just don't want to keep this "danger" from you. ;)

Accessing an array in one class from another class with C++

I'm having trouble trying to access an array used in my main class from another class. My application is an editor for making a 2d platform game - it basically allows you to place down 2D assets (segments) and build up a level.
My main class handles an array of map segment classes (each segment class in the array holds information such as position, scale and rotation of the segment on the map) and draws them to screen.
I have a separate class which is basically a panel (dragabble, and resizable like you would find in something like Photoshop) that is initialised in the main class and is used to draw a grid of available segments from a file. What I need is the ability to click on one of the segments which then adds information to the array that is referenced in the main class.
I have my main class "Map" which declares an array:
map.h (simplified)
class Map
{
public:
MapSegment* mapSeg[512];
};
I'm then trying to send a reference of that array when I create the panel to display the available segments, like so:
Panel* segmentPane = new SegmentPanel(sf::Rect<float>(200,200,250,200), mapSeg);
Segment Panel header is formed as follows:
class SegmentPanel : public Panel
{
public:
SegmentPanel(sf::Rect<float> _position, MapSegment* mapSeg[512];);
void Update();
void Draw(sf::RenderWindow & renderWindow);
void ReadSegments();
private:
std::vector<SegmentDefinition *> segDef;
MapSegment* mapSeg[512];
};
And SegmentPanel cpp:
SegmentPanel::SegmentPanel(sf::Rect<float> _position, MapSegment* mapSeg[512])
: Panel(_position)
{
panelTitle = "Segment Selection";
}
void SegmentPanel::Update()
{
// Update segments
}
void SegmentPanel::Draw(sf::RenderWindow & renderWindow)
{
// Draw default panel items
Panel::Draw(renderWindow);
// Draw segments
}
However, add elements to the array from SegmentPanel.cpp class doesn't seem to be reflected in my main Main class - it seems to create a new array in memory.
I'm still fairly new to C++ after working with C#!
First, there's no such thing as an array parameter type in C++. In your SegmentPanel constructor, the MapSegment* mapSeg[512] parameter is actually equivalent to MapSegment** mapSeg; it's just a pointer to a pointer!
Panel* segmentPane = new SegmentPanel(sf::Rect<float>(200,200,250,200), mapSeg);
Here, you attempt to pass the array mapSeg. This undergoes array-to-pointer conversion which turns it into a pointer to its first element (a MapSegment**) and then passes that pointer.
This is all fine, but you do nothing with the mapSeg argument in your constructor. If you want access to the array, you'll need to store that pointer somewhere. You can do that by changing the member of SegmentPanel called mapSeg to:
MapSegment** mapSeg;
Then change your constructor to:
SegmentPanel::SegmentPanel(sf::Rect<float> _position, MapSegment** mapSeg)
: Panel(_position), mapSeg(mapSeg)
{
panelTitle = "Segment Selection";
}
Note the initialisation of mapSeg in the member initialization list.
Another way you can do this is to take a reference to array type argument instead. Your constructor would now look like:
SegmentPanel::SegmentPanel(sf::Rect<float> _position, MapSegment* (&mapSeg)[512])
: Panel(_position), mapSeg(mapSeg)
{
panelTitle = "Segment Selection";
}
The type of the mapSeg argument is a "reference to array of 512 pointers to MapSegment". You'll then need to make the member mapSeg the same type.

c++ classes - how do I pass a function to an included class for it to use?

I'm sure this has something to do with virtual functions, but I'm struggling to work out how.
Here is my (simplified) situation:
Roughly what the program does is have one pair of files (computer.h) draw a computer with a blank screen, and another pair (program.h) which has a function that needs to draw on that computer screen
The computer class is going to be re-used in many different situations, so the screen draw function needs to be passed in a generic fashion
in computer.h:
include "screen.h"
class computer {
void drawComputer(); //this function draws a picture of a computer
void drawMonitor();
};
in computer.cpp:
void computer::drawComputer(){
//draws all the components then the monitor
drawMonitor(); //this is where the external function (from class screen) needs to execute
}
void computer::drawMonitor(){
//draws the background and border of screen
}
in program.h:
class program {
//many other program functions
void drawScreen();
};
in program.cpp:
//many other program functions
void program::drawScreen(){
//this function draws the contents of the screen
}
My question is, from program.cpp, how do I 'send' the drawScreen() function to execute within the drawMonitor() function in computer.cpp?
Edit
#Chris' solution seems to be nearly exactly what I am after, however when I attempt to implement it I get the following errors:
testApp.h:40: error: 'testApp::prog' cannot appear in a constant-expression
testApp.h:40: error: `&' cannot appear in a constant-expression
testApp.h:40: error: a cast to a type other than an integral or enumeration type cannot appear in a constant-expression
testApp.h:40: error: ISO C++ forbids initialization of member 'isprog'
testApp.h:40: error: making 'isprog' static
testApp.h:40: error: invalid in-class initialization of static data member of non-integral type 'IScreen*'
testApp.h:41: error: 'isprog' has not been declared
testApp.h:42: error: ISO C++ forbids declaration of 'comp1' with no type
testApp.h:42: error: expected ';' before '.' token
The lines are
39 Program prog;
40 IScreen *isprog = dynamic_cast<IScreen*>(&prog);
41 OP1 comp1(isprog);
42 comp1.drawScreen();
Anyone know where I'm going wrong with the implementation?
Well you're half-way there. For something like this, yes I'd use virtual functions (in order to define an abstract interface). Here's the basic outline of how I'd do it:
// First create a class to define an interface for drawing a screen
class IScreen
{
public:
// Defines an interface named drawScreen
virtual void drawScreen() = 0;
};
// Next actually implement the interface
class Program : public IScreen
{
public:
// Here we actually implement it
virtual void drawScreen()
{
// Draw some stuff here
}
};
// You can implement this more than once if you want
class BlueScreenOfDeathScreen : public IScreen
{
public:
virtual void drawScreen()
{
// Draw a BSOD on the screen
}
};
// Finally, use the interface
class Computer
{
private:
IScreen* myScreen;
public:
Computer(IScreen* screen)
: myScreen(screen)
{
}
void drawComputer()
{
// ...
}
void drawMonitor()
{
// Draw the monitor
// ...
// Draw the screen
myScreen->drawScreen();
}
};
Doing it this way, you can easily define multiple IScreen implementations and quickly swap them out with minimal changes to your code.
// Render using the "Program" class
Program prog;
IScreen *iprog = dynamic_cast<IScreen*>(&prog);
Computer comp1(iprog);
comp1.drawScreen();
// Render using the "BlueScreenOfDeathScreen" class
BlueScreenOfDeathScreen bsod;
IScreen *ibsod = dynamic_cast<IScreen*>(&bsod);
Computer comp2(ibsod);
comp2.drawScreen();
Easy, no?
You'd have to create an instance of program in your computer class, like so:
Program mypgm;
and then within your
void computer::drawMonitor(){
//draws the background and border of screen
mypgm.DrawScreen();
}
The most straight forward answer is to have an object of program inside computer and call drawScreen() from within. i.e.
class computer {
program prg; // <--- internal object
//...
};
void computer::drawMonitor() {
prg.drawScreen();
}
Another way is to pass an reference object of program to drawMonitor and call the method. i.e.
void computer::drawMonitor(program &prg) { // <--- pass by reference
prg.drawScreen();
}

Structure of program

I have few files:
main.cpp:
int main{
...
while(1){
...
draw();
...
}
...
return 0;
}
and draw.cpp:
I want to see objects and all manipulations here.
I cant make objects local to draw(), because draw() is inside loop,
so I will get many object constructor/destructor calls - so they are global. Also
I ve made init block to prevent unnecessary calls/assignments
draw.cpp:
Object A, B;
int initialized = 0;
void draw(){
if(!initialized){
A.initialization;
B.initialization;
initialized = 1;
}
A.move(1,1);
B.rotate(45);
}
It works, but Im looking for better way to organize my code
Added:
Thanks for answers, looks like I have to read something about pattern designs
Here's steps to make it work better:
Add a struct containing all your objects near main().
pass it to draw(MyStruct &s); via reference parameter.
you're done.
Option 1
Define a new Class called Draw and put the attributes into it. You need to modify main and draw files for this. With this you can avoid declaring anything global
Option 2
Define a class within draw.cpp called draw and add your current global variables as static member variables. Initialize and use them using static functions. With this you dont have to change main.
This design technique is called Singleton (one of the design patterns)
Example code
draw.cpp
class Draw
{
public:
object A, B;
static void init()
{
// init A
// init B
isInitialized = 1;
}
static int isInitialized;
static Object & getA()
{
if(isInitialized == 0)
{
init();
}
return A;
}
// similarly B
};