Friend function undeclared identifiers - c++

I'm working with OpenCV and Qt 5. I need to pass a mouse callback to a namedwindow for some work I'm doing. However, I can't get it to see any of the private member variables of my class.
Here's some code:
class testWizard : public QWizard
{
Q_OBJECT
public:
testWizard();
~testWizard();
friend void mouseHandler(int, int, int, void*);
private:
cv::Mat preview;
bool drag;
cv::Rect rect;
};
The friend function:
void mouseHandler(int event, int x, int y, void* param)
{
cv::Point p1, p2;
if(event == CV_EVENT_LBUTTONDOWN && !drag)
{
p1 = cv::Point(x,y);
drag = true;
}
if(event == CV_EVENT_LBUTTONDOWN && drag)
{
cv::Mat temp;
preview.copyTo(temp);
}
}
I don't know what I'm doing wrong. I'm pretty sure this is the correct way to declare this. It is telling me that preview, and drag are undeclared identifiers. Unfortunately I need to do it this way since I need access to the private members and passing a pointer to a member function isn't possible because of the hidden this argument.
Can anyone help? Thank you!

With the friend declaration your function would have access to the members of a testWizard object. However, you still need to provide an object or a pointer to such an object to access the variables:
testWizard* wizard = getTestWizard(); // no idea how to do that
if(event == CV_EVENT_LBUTTONDOWN && !wizard->drag) { ... }

Related

SFML calling parent's function from template derived class

I'm working on a custom project to learn SFML and I have a problem. I want to do a 'clickable' class where I could add some fancy function, my first goal to write an 'onMouseOver' function which could be nearly the same as in Javascript. This is the class:
template <class object>
class clickable: public object{
private:
sf::Vector2i mouse;
object& aim;
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const{ target.draw(aim, states); }
public:
clickable(sf::Vector2i mouse,object& aim):mouse(mouse),aim(aim){}
bool onMouseOver(sf::Vector2i mouse) {
float width = aim.getLocalBounds().width;
float height = aim.getLocalBounds().height;
if ((mouse.x >= aim.getPosition().x) && (mouse.x <= aim.getPosition().x + width) && (mouse.y >= aim.getPosition().y) && (mouse.y <= aim.getPosition().y + height))
return true;
else return false;
}
};
And here is my main:
int main()
{
sf::Font font;
if (!font.loadFromFile("arial.ttf")) {
std::cout << "Error!";
}
sf::RenderWindow window(sf::VideoMode(800, 600), "Title", sf::Style::Default);
sf::Vector2i mouse = sf::Mouse::getPosition(window);
vector<sf::Text> objects;
objects.push_back(sf::Text("Test text.", font, 14));
objects[0].setPosition(20, 20);
clickable<sf::Text> stuff(mouse,objects[0]);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
window.close();
}
if (event.type == sf::Event::MouseMoved) {
eger = sf::Mouse::getPosition(window);
}
}
window.clear();
window.draw(stuff);
if (stuff.onMouseOver(mouse)) objects[0].setFillColor(sf::Color::Red);
else objects[0].setFillColor(sf::Color::White);
window.display();
}
return 0;}
I tested this code (with different variable names, because I'm from Hungary) and it worked. My problem is that if I want to change the ' objects[0].setFillColor( sf::Color::Red ) ' to 'stuff.setFillColor(sf::Color::Red)' nothing happens on the screen. I assume that the problem is that I want to call an inherited parent-function from the child class, but I am not sure what could I do to solve the problem.
I hope it was understandable and sorry for the possible bad grammar, but I'm not a native speaker, as I mention above. Any help would be very appreciated!
Thanks in advance!
I have a very fast and easy quick fix for your problem. Simply add this line of code in your draw member function of your clickable class, before calling target.draw(aim, states); :
aim.setFillColor(this->getFillColor());
like this :
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const {
aim.setFillColor(this->getFillColor());
target.draw(aim, states);
}
or you can overload both setFillColor and getFillColor member functions :
void setFillColor(const sf::Color& c) {
aim.setFillColor(c);
}
const sf::Color& getFillColor() {
return aim.getFillColor();
}
Explanations :
You declared a variable stuff like this : clickable<sf::Text> stuff(mouse, objects[0]);
According to your template class definition, that means stuff is a clickable that inherits from sf::Text, so it's a clickable sf::Text, it's also a sf::Text.
Looking at the fields of your clickable class :
a sf::Vector2i mouse;
a object& aim;, the field aim is a reference at a object type, where object is your template parameter
so, your variable stuff holds all the data that a sf::Text object would hold, since stuff is a sf::Text, a sf::Vector2i, and a reference to a sf::Text object, which is not himself. So here, your stuff object can access 2 different sf::Text objects. Himself and the one referenced by aim.
You draw member function code shows that it draw the field aim, so the sf::Text referenced, and not the data held by himself
When, in your code, you do
objects[0].setFillColor( sf::Color::Red );
You call setFillColor method on the object that is referenced by the aim field of the stuff object, whereas that :
stuff.setFillColor(sf::Color::Red);
Changes the stuff object itself. And your draw function will draw the object referenced by the stuff object, but don't know at all modifications applied to the stuff object
So the solution is simple : all modifications applied to your stuff object need to be applied on the referenced object
You can do that when you want to draw your object ( in the draw method ) or when you ask to apply modifications ( when you call setFillColor method for example ).
By the way, Alex is right on the fact that your class is not really well designed. You can also not hold reference on sf::Text object and call the sf::Text draw method for (*this) ( or just don't overload the draw method in the clickable object and do proper copy of the sf::Text in your object )
You have two different objects of type sf::Text:
stuff
stuff's data member called aim
Calling the setFillColor method of stuff will set stuff's fill color, not aim's. But the draw method of stuff defers completely to the draw method of aim:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const{ target.draw(aim, states); }
aim is ignorant of stuff's fill color, so window.draw(stuff) will do exactly the same thing as before.
The solution is to redesign your clickable class, and that depends on your intentions. Why do you want to both inherit from the template class and have a data member of that class type?
The simplest thing to do right now is probably to reimplement the setFillColor method of sf::Text as a new method of clickable:
void clickable::setFillColor( const Color & color ) {
aim.setFillColor( color );
}
Thanks you both of you, now I got it I understand! Both of explanations were good. I redesigned the class, for the following stucked programmers here is my solution:
template <class object>
class clickable: public object{
public:
clickable(const string& s, const sf::Font& f, unsigned int size) : object::Text(s, f, size) {}
void cmd_out() {
cout << (string) (*this).getString();
}
void graph_out(float x = 0, float y = 0) {
}
bool onMouseOver(const sf::Vector2i& eger) {
float width = (*this).getLocalBounds().width;
float height = (*this).getLocalBounds().height;
if ((eger.x >= (*this).getPosition().x) && (eger.x <= (*this).getPosition().x + width) && (eger.y >= (*this).getPosition().y) && (eger.y <= (*this).getPosition().y + height))
return true;
else return false;
}
};
Now it's working, but I can only make with this sf::Text clickable objects, but in case if I would need any other, it would be easy to add another contructor based on which is required.

C++ passing a list of a class with elements of a subclass

I am sort of a noob in C++ and I am trying to make a simplegame. This is my problem:
I created class called sprite:
class Sprite
{
private:
Point2D sp_pos;
Point2D sp_vel;
SDL_Surface* sp_img;
Point2D sp_center;
Point2D sp_size;
double sp_radius;
bool sp_animated;
int sp_frames;
int sp_cur_frame;
public:
Sprite() {}
Sprite(Point2D pos, Point2D vel, SDL_Surface *img, ImageInfo info, bool animated = false, int frames = 0);
virtual void draw(SDL_Surface* screen);
virtual void update();
void setInfo (ImageInfo info);
void setPos( Point2D pos ) { sp_pos = pos; }
void setVel( Point2D vel ) { sp_vel = vel; }
void setImg (SDL_Surface* img) { sp_img = img; }
void setNextFrame() { sp_cur_frame++; }
void setFrame( int frame ) { sp_cur_frame = frame; }
void setAnimated(bool animated) { sp_animated = animated; }
void changeVelX (int c) { sp_vel.setX(c);}
void changeVelY (int c) { sp_vel.setY(c);}
void changePosX (int c) { sp_pos.setX(c);}
void changePosY (int c) { sp_pos.setY(c);}
SDL_Surface* getImg() { return sp_img; }
Point2D getPos() { return sp_pos; }
Point2D getVel() { return sp_vel; }
Point2D getCenter() { return sp_center; }
Point2D getSize() { return sp_size; }
double getRadius() { return sp_radius; }
int getCurFrame() { return sp_cur_frame; }
int getFrames() { return sp_frames; }
bool collide(Sprite &another_sprite);
};
Which has a method called "collide", this method detects a collision between two sprites, and works as follows:
bool Sprite::collide(Sprite &another_sprite)
{
double d = getPos().dist(another_sprite.getPos());
if ( d < ( getRadius() + another_sprite.getRadius() ) )
return true;
else
return false;
}
The method works fine. My problem arises with the following, I have implemented different classes that are subclasses of "Sprite" and will represent enemies in my game, so, for instance I would have objects: Class enemy1 : public Sprite, Class enemy2 : public Sprite, etc. They are different because they have different behaviors. I implemented other two helper functions called group_collide and group_group_collide, that work as follows:
bool group_collide(std::list<Sprite> &group, Sprite other_object)
{
bool collision = false;
for (std::list<Sprite>::iterator sprite = group.begin(), end = group.end(); sprite != end; ++sprite)
{
if (sprite->collide(other_object))
{
Sprite exp = Sprite(sprite->getPos(), Point2D(0, 0), exp_image, exp_info, true, 7);
exp_group.push_back(exp);
if( Mix_PlayChannel( -1, explosion, 0 ) == -1 )
{
//abort();
}
sprite = group.erase(sprite);
collision = true;
}
}
return collision;
}
int group_group_collide(std::list<Sprite> &group, std::list<Sprite> &other_group)
{
int scored = 0;
for (std::list<Sprite>::iterator it1 = group.begin(), end1 = group.end(); it1 != end1; ++it1)
{
if (group_collide(other_group, *it1))
{
it1 = group.erase(it1);
scored += 10;
}
}
return scored;
}
So, in fact, group collide will detect collisons between a sprite and a list of sprites, and group_group_collide will detect collisions between group of sprites (two different lists). The problem that arises is: There will be at least 4 types of enemies, and all of them are subclasses of my Sprite class, but I get compilation errors when I create a list of sprites and add elements that are subclasses of sprites. My solution was writing a method group_collide and group_group collide for all types of enemies, but this is quite inelegant. Is there a better way to approach this problem?
EDIT:
Thanks for your suggestions. I defined the list as a pointers list as you have suggested:
std::list<Sprite*> enemy_group;
And for instance, I am adding elements of class "Kamikaze" which is a subclass of sprite, in this way (the method update is different in this class):
enemy_group.push_back(new Kamikaze(enemy_pos, enemy_vel, 0, enemy_image, enemy_info));
However, when iterating over the list:
for (list<Sprite*>::iterator it = enemy_group.begin(), end = enemy_group.end(); it != end; ++it) {
(*it)->draw(screen);
(*it)->update();
if ((*it)->getPos().getY() > SCREEN_HEIGHT + 30)
{
delete *it;
it = enemy_group.erase(it);
}
}
The method update is called from the Sprite class, not Kamikaze class, therefore I also have object slicing problem with this approach, perhaps there is something wrong with what I have done?
I get compilation errors when I create a list of sprites and add elements that are subclasses of sprites.
All derived classes will be 'sliced' in order to fit into an object container like std::list. A std::list<Sprite*> //(Preferably a smart pointer) will avoid this problem, though the actual objects would have to be stored elsewhere.
As given in the answer by Laserbreath, you should replace std::list<Sprite> with std::list<Sprite*>. Currently, any passed subclass will be reduced to Sprite. Using a list of pointers you can avoid that.
You should use virtual functions to get the desired result.
In base class:
//This way you'll have a default collision method for a Sprite...
//...but you'll be able to re-define it in subclasses.
//I don't do THIS ONE often so I'm not sure if you'll have to perform additional steps
virtual bool Sprite::collide(Sprite &another_sprite)
{
...
}
//And this way you are making collied a pure virtual function and Sprite an abstract class...
//...meaning you can't instantiate it, but you can use it with a pointer or reference.
//Every subclass of Sprite must have a body of function collide defined
//you do this only in header of class Sprite
virtual bool virtual bool Sprite::collide(Sprite &another_sprite) = 0;
In sub-class
//if you have made collide pure virtual function, you can do this
//not sure about the first case though
bool SubSprite::collide(Sprite &another_sprite)
{
...
}
So, when collide method is called from a Sprite pointer or reference, the call will be re-directed to the designated function of a subclass.
Same goes for group_collide.
ADDITIONAL EXPLANATION:
//lets assumme you have 2 sprite types, Kamikaze and NotKamikaze
Sprite *sprite1 = new Kamikaze();
Sprite *sprite2 = new NotKamikaze();
//and lets assume collide uses pointer instead, just for this example, so it's shorter
virtual bool Sprite::collide(Sprite *another_sprite) = 0;
bool Kamikaze::collide(Sprite *another_sprite);
bool NotKamikaze::collide(Sprite *another_sprite);
//when you call collide from Sprite*, it **automatically** picks the sub-class collude method
//sprite1 is of type Sprite*, but allocated memory is of Kamikaze
//so the only function called is Kamikaze::collide
sprite1->collide(sprite2);
//sprite2 is of type Sprite*, but allocated memory is of NotKamikaze
//so the only function called is NotKamikaze::collide
sprite2->collide(sprite2);
So whenever a pure virtual function collide is called from pointer or reference, the program automatically selects the right one. If you want it to be different for every sprite type, then this is what you need.
This is where "object slicing" becomes the issue. Sprite can exist as a pointer or reference, but only to a non-abstract sub-class. So Sprite *Sprite sprite1 = new Sprite(); won't work, but Sprite *Sprite sprite1 = new SpriteSubClass(); works.
If you make Sprite::collide not purely virtual, Sprite would no longer be an abstract class, and you could make the method run from Sprite class itself, and you could do Sprite *Sprite sprite1 = new Sprite();. But I highly doubt you'll need that as you're only looking at subclasses.
Whenever a method name is shared, but its behavior differs by subclass, it must be virtual.

Using Setters and Getters in AlgorithmInfo::addParam for Algorithm inheritance

I am working on creating my own algorithm inheriting from cv::Algorithm using the reference from the OpenCV docs. I have created my own classes that inherit from cv::Algorithm with success but I am having difficulty with this one since it has a member m_model which is a stuct from a library that can't be modified because the MyAlgorithm class is wrapping the functionality in this struct.
Anyways, I am trying to reference a member within the struct that is a `uchar[3] so I wrapped it in a cv::Ptr.
When I compile my program without and getters or setters on the addParam method
obj.info()->addParam<uchar[3]>(obj, "arrPtr", *arrPtr, false);
the code compiles fine but I get a runtime error when I try to write an MyAlgorithm object to file because it can't get the data. It is looking for a member variable with the arr name but it doesn't exist. So I defined some getter and setter methods for the arr parameter within the m_model class member.
However, I am not sure how to pass the member function pointers into the addParams method. I know that I can't just pass them into the addParams method like a function like I am currently doing in the code below. I have also tried the following:
obj.info()->addParam<uchar[3]>(obj, "arr", *arrPtr, false, &MyAlgorithm::getArr, &MyAlgorithm::setArr);
but I get a compile error:
cannot convert parameter 5 from 'cv::Ptr<_Tp> (__thiscall MyAlgorithm::* )(void)' to 'cv::Ptr<_Tp> (__thiscall cv::Algorithm::* )(void)'
Below is a stripped down sample of my source code. Any help would be greatly appreciated.
my_algorithm.h
class MyAlgorithm : public cv::Algorithm {
public:
//Other class logic
cv::Ptr<uchar[3]> getArr();
void setArr(const cv::Ptr<uchar[3]> &arrPtr);
virtual cv::AlgorithmInfo* info() const;
protected:
//define members such as m_model
};
cv::Algorithm* createMyAlgorithm();
cv::AlgorithmInfo& MyAlgorithm_info();
my_algorithm.cpp
cv::Algorithm* createMyAlgorithm()
{
return new MyAlgorithm();
}
cv::AlgorithmInfo& MyAlgorithm_info()
{
static cv::AlgorithmInfo MyAlgorithm_info_var("MyAlgorithm", createMyAlgorithm);
return MyAlgorithm_info_var;
}
cv::AlgorithmInfo* MyAlgorithm::info() const
{
static volatile bool initialized = false;
if( !initialized )
{
initialized = true;
MyAlgorithm obj;
cv::Ptr<uchar[3]> *arrPtr = new cv::Ptr<uchar[3]>(&(obj.m_model->arr));
obj.info()->addParam<uchar[3]>(obj, "arr", *arrPtr, false, &getArr, &setArr);
}
return &MyAlgorithm_info();
}
cv::Ptr<uchar[3]> MyAlgorithm::getArr(){
//Logic to get arr
}
void MyAlgorithm::setArr(const cv::Ptr<uchar[3]> &arrPtr){
//Logic to set arr
}
I managed to get the setter and getter for the addParam method to work. The issue was that I needed to perform a static_cast to the parent class like so:
typedef cv::Ptr<uchar[3]> (cv::Algorithm::*ArrGetter)();
typedef void (cv::Algorithm::*ArrSetter)(const cv::Ptr<uchar[3]> &);
obj.info()->addParam<uchar[3]>(obj, "arr", *arrPtr, false, static_cast<ArrGetter>(&MyAlgorithm::getArr), static_cast<ArrSetter>(&MyAlgorithm::setArr));
However, I also found that OpenCV doesn't know how to handle the read and writes of a uchar[3]. I tried a cv::Vec3b which didn't seem to work either so I settled on a cv::Mat using the setters and getters. So the final solution looks something like this.
my_algorithm.h
class MyAlgorithm : public cv::Algorithm {
public:
typedef cv::Mat (cv::Algorithm::*ArrGetter)();
typedef void (cv::Algorithm::*ArrSetter)(const cv::Mat &);
//Other class logic
cv::Mat getArr();
void setArr(const cv::Mat &arrPtr);
virtual cv::AlgorithmInfo* info() const;
protected:
uchar[3] arr;
};
cv::Algorithm* createMyAlgorithm();
cv::AlgorithmInfo& MyAlgorithm_info();
my_algorithm.cpp
cv::AlgorithmInfo* MyAlgorithm::info() const
{
static volatile bool initialized = false;
if( !initialized )
{
initialized = true;
MyAlgorithm obj;
cv::Vec3b arrVec(arr);
obj.info()->addParam(obj, "arr", (cv::Mat)arrVec, false, static_cast<ArrGetter>(&MyAlgorithm::getArr), static_cast<ArrSetter>(&MyAlgorithm::setArr));
}
return &MyAlgorithm_info();
}
cv::Mat MyAlgorithm::getArr(){
cv::Vec3b arrVec(arr);
return (cv::Mat)arrVec;
}
void MyAlgorithm::setArr(const cv::Mat &arrMat){
for (int i = 0; i < 3; i++)
arr[i] = arrMat.at<uchar>(i);
}

c++: exact type of contained objects without casts

I got the classic Shape hierarchy example...
struct Shape { // abstract type
Shape (int x, int y);
int x;
int y;
};
struct Rectangle : public Shape {
Rectangle (int x, int y, int w, int h);
int w;
int h;
};
struct Circle : public Shape {
Circle (int x, int y, int r);
int r;
};
a Shapes container, filled with Rectangles and Circles
std::list<Shape*> container;
and printing functions (in my case, those are collision detection functions)
void print_types (Shape&, Shape&) {
std::cout << "Shape, Shape" << std::endl;
}
void print_types (Rectangle&, Rectangle&) {
std::cout << "Rectangle, Rectangle" << std::endl;
}
void print_types (Rectangle&, Circle&) {
...
Course, when I'm doing this:
std::list<Shape*> it;
Rectangle r (0, 0, 32, 32);
for (it = container.begin(); it != container.end(); it++)
print_types(r, **it);
I don't want to print only "Shape, Shape" lines. I know virtual methods, dynamic_casts and visitors. But is there any elegant way to get out of it without those solutions and keep my external functions ?
You should probably stick with virtual functions and have only one print_types function
void print_types(Shape&)
Then add a virtual PrintName function to the base class and override it in the derived class.
This IS the most elegant way.
The short answer is no, function calls are resolved at compile-time. So there is no way (AFAIK) to do this with your existing free functions.
I believe you will have to invest in a double-dispatch mechanism, or do what #Peter suggests in his answer (which sounds more elegant).
I can't call it elegant, and it has several pitfalls, but the classic way to do this before dynamic_cast was to have a virtual function, say virtual char* name(), in Shape and have each derived class override that function to return the correct name.
The most obvious pitfall is that you must maintain the whole thing by hand.
Responding to the edit of the problem:
The best solution is still to find a virtual method that will deliver what is required. For detecting shape collisions, perhaps you could have a function that converts each shape to a polygon (set of lines) and do the detection on that.
C++ uses the type you declared at compile-time to select which overloaded function to call; it doesn't have the ability to make that selection at run-time. That's why you're seeing "Shape,Shape" as output each time. There's a way to help the compiler out but it's going to be tedious. Try to convert each Shape* to the appropriate type, and if it succeeds you can call a more specific function.
I'm not really advocating this; you can see how it gets out of hand with just two shapes, imagine how ugly it gets as you add more! Still it shows how to do what you were trying to do in C++.
void print_types (Rectangle*, Rectangle*) {
std::cout << "Rectangle, Rectangle" << std::endl;
}
void print_types (Rectangle*, Circle*) {
...
void print_types (Rectangle* left, Shape* right) {
Rectangle* rightRect = dynamic_cast<Rectangle*>(right);
if (rightRect != NULL) {
print_types(left, rightRect);
return;
}
Circle* rightCirc = dynamic_cast<Circle*>(right);
if (rightCirc != NULL) {
print_types(left, rightCirc);
return;
}
throw /* something to indicate invalid shape */;
}
void print_types (Circle* left, Shape* right) {
...
void print_types (Shape* left, Shape* right) {
Rectangle* leftRect = dynamic_cast<Rectangle*>(left);
if (leftRect != NULL) {
print_types(leftRect, right);
return;
}
Circle* leftCirc = dynamic_cast<Circle*>(left);
if (leftCirc != NULL) {
print_types(leftCirc, right);
return;
}
throw /* something to indicate invalid shape */;
}

C2664 error in an attempt to do some OpenGl in c++

Here is an abstract of my code. I'm trying to use glutSpecialFunc to tell glut to use my KeyPress function
class Car : public WorldObject
{
public:
void KeyPress(int key, int x, int y)
{
}
Car()
{
glutSpecialFunc(&Car::KeyPress); // C2664 error
}
}
The error message I get is:
Error 1 error C2664: 'glutSpecialFunc' : cannot convert parameter 1 from 'void (__thiscall Car::* )(int,int,int)' to 'void (__cdecl *)(int,int,int)' c:\users\thorgeir\desktop\programmingproject1\quickness\quickness\car.cpp 18 Quickness
Your function is a member of a class. When you do something like Car c; c.drive(), that drive() function needs a car to work with. That is the this pointer. So glut can't call that function if it doesn't have a car to work on, it's expecting a free function.
You could make your function static, which would mean the function does not operate on a car. glut will then be able to call it, however I assume you want to manipulate a car. The solution is to make the function pass it's call onto an object, like this:
void key_press(int key, int x, int y)
{
activeCar->KeyPress(key, x, y);
}
Where activeCar is some globally accessible pointer to car. You can do this with some sort of CarManager singleton.
CarManager keeps track of the active car being controlled, so when a key is pressed you can pass it on: CarManager::reference().active_car().KeyPress(key, x, y).
A singleton is an object that has only one globally accessible instance. It is outside the scope of the answer, but you can Google for various resources on creating one. Look up Meyers Singleton for a simple singleton solution.
A different approach is to have a sort of InputManager singleton, and this manager will keep track of a list of objects it should notify of key presses. This can be done in a few ways, the easiest would be something like this:
class InputListener;
class InputManager
{
public:
// ...
void register_listener(InputListener *listener)
{
_listeners.push_back(listener);
}
void unregister_listener(InputListener *listener)
{
_listeners.erase(std::find(_listeners.begin(), _listeners.end(), listener));
}
// ...
private:
// types
typedef std::vector<InputListener*> container;
// global KeyPress function, you can register this in the constructor
// of InputManager, by calling glutSpecialFunc
static void KeyPress(int key, int x, int y)
{
// singleton method to get a reference to the instance
reference().handle_key_press(key, x, y);
}
void handle_key_press(int key, int x, int y) const
{
for (container::const_iterator iter = _listeners.begin();
iter != _listenders.end(), ++iter)
{
iter->KeyPress(key, x, y);
}
}
container _listeners;
};
class InputListener
{
public:
// creation
InputListener(void)
{
// automatically add to manager
InputManager::reference().register_listener(this);
}
virtual ~InputListener(void)
{
// unregister
InputManager::reference().unregister_listener(this);
}
// this will be implemented to handle input
virtual void KeyPress(int key, int x, int y) = 0;
};
class Car : public InputListener
{
// implement input handler
void KeyPress(int key, int x, int y)
{
// ...
}
};
Of course feel free to ask more questions if this doesn't make sense.
What I ended up doing was
Adding:
virtual void KeyPress(int key, int x, int y) {};
to the WorldObject class
And bubble the event to the Car.
void KeyPressed(int key, int x, int y)
{
KeyPress(key,x,y);
list<WorldObject*>::iterator iterator = ChildObjects.begin();
while(iterator != ChildObjects.end())
{
(*iterator)->KeyPressed(key,x,y);
iterator++;
}
}