C++ Function Pointers using class T [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I am working on my own GUI framework using C++ and OpenGL. My experience in both is small as this is my first project using them.
In the framework I have created a window, which renders the design of the window, and then any objects that have been added to the window as a child.
I then create the window using a new class called MainMenu that inherits from my window class, I then add a new button to the MainMenu
Using:
button->SetOnClick(&MainMenu::button_Click, this);
I then add a pointer to the function, as well as the instance of the class to the buttons 'SetOnClick' method - Therefore if that button is clicked a method within the MainMenu will run.
This works great at the moment, however my issue now is that I want to add a new window called Settings, which will also inherit from the Window class
Therefore I need to make the function pointer in my button class work for any number of classes (all of type Window)
Here is the code that is currently working - but for only the MainMenu (Please note that I have stripped out a lot of methods that do not relate to the question to make it easier to read)
Window.h:
class Window
{
private:
void Initialize(WindowManager* manager, int width, int height);
public:
Window(WindowManager* manager);
Window(WindowManager* manager, int width, int height);
~Window(void);
void Render();
bool MouseMove(int x, int y);
bool MouseLBDown(int x, int y);
Children* Child() { return m_children; };
MainMenu.h:
class MainMenu : public ObjWindow
{
private:
void Initialize();
public:
MainMenu(WindowManager* manager, int width, int height) : Window(manager, width, height)
{
Initialize();
};
MainMenu(WindowManager* manager) : Window(manager)
{
Initialize();
};
~MainMenu(void);
void button_Click();
MainMenu.cpp:
void MainMenu::Initialize()
{
Button* button = new Button(Vector2D(100, -400), 100, 50);
Child()->Add(button);
button->SetText("Click Me!");
button->SetOnClick(&MainMenu::button_Click, this);
}
void MainMenu::button_Click()
{
//Do some button code
}
Button.h:
class Button
{
typedef void (MainMenu::*Function)();
Function m_onClickFunction;
MainMenu* m_window;
public:
Button(Vector2D position, int width, int height);
~Button(void);
void SetText(std::string);
std::string GetText();
void Render();
bool MouseMove(int x, int y);
bool MouseLBDown(int x, int y);
void SetOnClick(Function, MainMenu*);
Button.cpp:
Button::Button(Vector2D position, int width, int height)
{
m_onClickFunction = NULL;
}
Button::~Button(void)
{
}
bool Button::MouseMove(int x, int y)
{
return true;
}
bool Button::MouseLBDown(int x, int y)
{
if (m_body->Intercepts(x,y))
{
if (m_onClickFunction != NULL)
{
(m_window->*m_onClickFunction)();
}
}
return true;
}
void Button::SetOnClick(Function function, MainMenu* window)
{
m_onClickFunction = function;
m_window = window;
}
From researching around the internet it seems that I need to use a template so that I can handle the class as a type, I have tried fitting this in to my code, but so far I nothing has worked.
Please note that I am also new to asking question on stackoverflow, so if I am missing anything important please let me know

You need to either create a template of the Button class - in your case it would look like this:
template <typename myType>
class Button{
typedef void (myType::*Function)();
Function m_onClickFunction;
myType* m_window;
public:
...
void SetOnClick(Function, myType*);
}
And use it like this:
Button<MainMenu> button;
button->SetOnClick(&MainMenu::button_Click, this);
...or create a delegate class. There are plenty of examples about delegates in C++, if you search for them.
But I'm not so sure if you wan't to stick with passing pointers to functions. You might be better off always calling the same method of derived classes, and using the virtual keyword.
Like this:
class Window{
public:
virtual void button_Click(){};
};
class someDerivedWindow: public Window{
public:
void button_Click(){};
};
and inside the button class just calling:
m_window->button_Click();

You could work and implement your own library to do member function pointers, depending on what the goal of your project is. It is fairly complicated though, and requires a rather deep understanding of C++.
However, you can also use boost::function combined with std::bind or boost:bind, to achieve what you want to do.
If you have
struct X {
int foo(int);
};
You can use:
boost::function1<int, int> f;
X x;
f = std::bind1st(
std::mem_fun(&X::foo), &x);
f(5); // Call x.foo(5)
This example is taken directly from the boost::function documentation - http://www.boost.org/doc/libs/1_55_0/doc/html/function.html

If using C++11:
#include <iostream>
#include <functional>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <ctime>
using namespace std;
int foo1()
{
return 0;
}
int foo2()
{
return 1;
}
int main()
{
function<int()> f1 = foo1;
function<int()> f2 = foo2;
//do some magic
srand(time(0));
function<function<int()>()> generator = [&]()
{
if(rand() % 2 == 0)
return foo1;
else
return foo2;
};
vector<function<int()>> vec(100);
generate(vec.begin(),vec.end(),generator);
for(auto elem: vec)
cout << elem() << endl;
return 0;
}

Related

C++, How to call a child method in the parent class

I have two classes in my project:
Style
Line
In which, Line is the child of Style, so Line inherits from Style.
I need that when I call a method of the class Style (the parent) from Line (the child), the method of Style calls a method of the child, for your better understanding here is the code:
Line calls the Style function --> Style calls the Line function
Style.h:
#pragma once
class Style
{
public:
void set_size(int width, int height);
protected:
int width, height;
};
Style.cpp:
#include "Style.h"
void Style::set_size(int width, int height)
{
Style::width = width;
Style::height = height;
}
Line.h:
#pragma once
#include "Style.h"
#include <vector>
using namespace std;
class Line : public Style
{
public:
void draw();
vector <vector<char>> matrix;
};
Line.cpp:
#include "Line.h"
void Line::draw()
{
vector <char> row;
int i, j;
for (i = 0; i < Line::height; i++)
{
row.clear();
for (j = 0; j < Line::height; i++)
{
row.push_back('-');
}
Line::matrix.push_back(row);
}
}
Main.cpp:
#include <iostream>
#include "Line.h"
using namespace std;
int main()
{
Line line;
line.set_size(10, 10);
}
Obviously, this code for now does nothing much, it only modifies Style variables.
What I expect is that when I call set_size(), in addition to changing the value of the variables width and height, it will also change the size of the matrix
I don't know how to do what I said before.
I don't even know if it is a good method that Line is a child of Style, in any case other solutions that do not include inheritance are welcome.
Thanks in advance.
You need virtual functions, it would seem that set_size is the one that should be virtual, but this is not the only way to do it.
class Style
{
public:
virtual void set_size(int width, int height);
virtual ~Style() {}
protected:
int width, height;
};
class Line : public Style
{
public:
void draw();
virtual void set_size(int width, int height)
{
Style::set_size(width, height);
... // some code to resize matrix
}
vector <vector<char>> matrix;
};
But I question if this is good design, Style should be an attribute of Line (i.e. a member variable). Inheritance doesn't seem appropriate here, which is why you are struggling to write the code.
I tried to have implementation and declaration in the same file. but you can structure it as you may feel good for your project.
#include <iostream>
#include <vector>
using namespace std;
class Line;
class Style
{
public:
void set_size(int width, int height){
w = width;
h = height;
}
void print(){
cout << w << ", " << h << endl;
}
friend class Line;
protected:
int w, h;
};
class Line : public Style
{
public:
void draw(){
vector <char> row;
int i, j;
for (i = 0; i < w; i++)
{
row.clear();
for (j = 0; j < h; i++)
{
row.push_back('-');
}
matrix.push_back(row);
}
}
vector<vector<char>> matrix;
};
int main()
{
Line line;
line.set_size(10, 10);
line.print();
line.set_size(20, 20);
line.print();
}
We can just overload set_size within Line and call the other set_size from there and also the draw function to recreate the matrix.
This solution provides simple static polymorphism, that means a Line cannot be assigned to a Style - you probably do not need this? So the compiler always statically at compile-time knows, which class an object really is and can call the correct member function. No virtual member functions are needed.
There also were bugs in the draw function, which I corrected below.
The changes to your code are marked with a comment in the following.
// Line.h
#pragma once
#include "Style.h"
#include <vector>
using namespace std;
class Line : private Style // use private inheritance for static polymorphism
{
public:
void draw();
void set_size(int width, int height); // overload set_size (override only for virtual functions)
vector <vector<char>> matrix;
};
// Line.cpp
#include "Line.h"
void Line::set_size(int width, int height)
{
Style::set_size(width, height); // call set_size() function of style
draw(); // draw() to set matrix to new size
}
void Line::draw()
{
Line::matrix.clear(); // clear matrix, if draw() is called more than once
vector <char> row;
int i, j;
for (i = 0; i < Line::height; i++)
{
row.clear();
for (j = 0; j < Line::width; j++) // use Line::width and j++ (there were bugs)
{
row.push_back('-');
}
Line::matrix.push_back(row);
}
}
// Main.cpp
#include <iostream>
#include "Line.h"
using namespace std;
int main()
{
Line line;
line.set_size(10, 10); // calls the enhanced Line::set_size
// The following compilation errors (when the comments are removed) are good, as they prevent wrong usage of the current class definitions
// Style style = line; // would give error, as we have private inheritance and want to prevent 'slicing' and the calling of the wrong member functions; if a Line should be able to be assigned to a Style, you need public dynamic inheritance and virtual functions, as provided in other answers. If you do not need to assign a Line to a Style, use the simpler implementation from this answer.
// Style* stylepointer = &line; // also would give an error
}
Optionally draw() and matrix can be made private in Line.
If you need to call functions (other than set_size) of Style directly, you can use public inheritance, but make all constructors (including default/copy/move) of Style protected, so that only children like Line can call them. This would also prevent assignments of Line to Style.
EDIT: I'm completely changing the original answer since the question was modified too. If I get it right, you would like line.set_size(...) to call first the parent method and then to update the matrix. You cannot do that, because only one method will be called, and not both of them what you could do is add a set_size method for Line that calls Style's one.
line.h should be changed like this:
class Line : public Style
{
public:
void draw();
void set_size(int width, int height);
vector<vector<char>> matrix;
};
and you should append this to line.cpp:
void Line::set_size(int width, int height)
{
// call parent method
Style::set_size(width, height);
// now update matrix
int i, j;
matrix.resize(height);
for (auto &row : matrix)
{
row.resize(width);
}
}
Hope it helps!
Base function must be virtual for runtime inheritance.
as follows example
class base {
public:
virtual void print()
{
cout << "print base class\n";
}
void show()
{
cout << "show base class\n";
}
};
class derived : public base {
public:
void print()
{
cout << "print derived class\n";
}
void show()
{
cout << "show derived class\n";
}
};
int main()
{
base *bptr;
derived d;
bptr = &d;
// Virtual function, binded at runtime
bptr->print();
// Non-virtual function, binded at compile time
bptr->show();
return 0;
}

glfw non-standard syntax; use '&' to create a pointer to member

i keep getting non-standard syntax; use '&' to create a pointer to member
i dont know why its not working.
it works if Resize function is global
minimal example:
#include <GLFW/glfw3.h>
class test {
public:
test(){}
~test(){}
void resize(GLFWwindow* window, int new_width, int new_height) {}
}resizer;
int main(){
auto newwindow = glfwCreateWindow(1, 1, "test", NULL, NULL);
glfwSetWindowSizeCallback(newwindow, resizer.resize);
return 0;
}
the initial problem got kinda solved using static as the function but this created diferent errors in what i want to do here is the simplified problem the problem:
//rough replication of lib functions cannot change these
typedef void(* windowsizefun)(int,int);
void setWindowSizeCallback(windowsizefun fun){}
//the problem
class windowhandler{
private:
int width, height;
static void resize(int new_width, int new_height) {
width =new_width; height =new_height; //error
}
public:
test(){
width =100; height =100;
setWindowSizeCallback(windowhandler::resize);
}
}
int main(){
windowhandler newWindow();
return 0;
}
Your function pointer doesn't match the declaration that's needed to pass into glfwSetWindowSizeCallback().
It must be a static function, and the scope operator :: needs to be applied correctly:
#include <GLFW/glfw3.h>
class test {
public:
test(){}
~test(){}
static void resize(GLFWwindow* window, int new_width, int new_height) {}
// ^^^^^^
} /*resizer*/;
// ^^^^^^^^^^^ No need for this.
int main(){
auto newwindow = glfwCreateWindow(1, 1, "test", NULL, NULL);
glfwSetWindowSizeCallback(newwindow, test::resize);
return 0;
}

FLTK C++ Fl_line don't draw

I was tasked to debug a code that was meant to draw a simple polygon out of 4 points using FLTK. The MyWindow class derive from Fl_Window. The Shape class is the parent class for ClosedPolyline. Both MyWindow and Shape hold a vector to draw all of the shapes.
The problem is that after compiling and run, win.show() opens an empty window without any drawing. I'm puzzled to understand this behavior.
Here is the code (I've omitted some of the parts that are not related to drawing ClosedPolyline):
#include <iostream>
#include <FL/Fl.H>
#include <FL/Fl_Draw.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Device.H>
#include <initializer_list>
#include <vector>
#include <functional>
//#include <cmath>
//#include <math.h>
struct Point {
int x,y;
Point(int xx, int yy) : x(xx), y(yy) { }
};
class Shape{
public:
Point point(int idx) const {
return (points[idx]);
}
unsigned int points_size() const {
return points.size();}
void draw() /*const*/{
draw_lines();
}
void add(Point p){ points.push_back(p); }
protected:
virtual void draw_lines() {}
private:
std::vector<Point> points;
};
class ClosedPolyline: public Shape {
public:
/*ClosedPolyline(std::initializer_list<Point> pp) {
if (pp.size() > 0) {
for (Point p: pp)
add(p);
}
}
*/
ClosedPolyline(Point a1, Point a2, Point a3, Point a4){
add(a1); add(a2); add(a3); add(a4);
}
protected:
void draw_lines() override{
for (unsigned int i=1; i<points_size(); ++i){
fl_line(point(i-1).x, point(i-1).y, point(i).x, point(i).y);
}
}
};
class MyWindow: public Fl_Window {
public:
MyWindow(int x, int y, int w, int h, const char* title = 0)
: Fl_Window(x, y, w, h, title) {}
void Attach(Shape s) {
shapes.push_back(&s);
}
//void draw_shapes(){draw();}
protected:
void draw() override{
for(Shape * s: shapes) {
s->draw();
//s.draw();
}
}
private:
std::vector<Shape*> shapes;
};
And here is the main() function:
int main() {
MyWindow win(100, 100, 600, 400, "C++ Test task");
ClosedPolyline p{Point{100, 100}, Point{100, 200}, Point{500, 100}, Point{500, 200}};
win.Attach(p);
win.end();
win.show();
return (Fl::run());
}
Lets take a look at your MyWindow::Attach function:
void Attach(Shape s) {
shapes.push_back(&s);
}
In the function, the argument s is passed by value. That means it's the same as a local variable inside the function. And as such it will go out of scope and be destructed once the function return.
Saving a pointer to that variable will lead to you saving a stray pointer, pointing to a non-existing object. Dereferencing that pointer will lead to undefined behavior, turning your whole program ill-formed and invalid.
One way to solve the problem is to make sure that the object don't go out of scope. This can be done by using smart pointers like e.g. std::unique_ptr. And to use it from the beginning already when you define the variable p in the main function.
Another way to solve your problem is to assume that the Shape passed to Attach will have a lifetime that outlives the Shape object, and you could therefore pass the Shape by reference:
void Attach(Shape& s) {
shapes.push_back(&s);
}
Now you no longer get a copy of the Shape object, and push a pointer to the original object (in your case the object p in the main function). Dereferencing the pointer will be valid as long as the original object is alive and in scope.
I try run that code in VS2015 and get a lot of error( of course fix attach window pass by reference ) But when I run to linux , it can draw, So I think you should move to linux.

Create a variable inside another statement [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
Is there a way to allocate a variable within the scope of a parameter list? By using new we can do the following :
Class A{ /*... snip ...*/ };
void myFunc(A* a){ }
int main(...){
myFunc(new A());
return 0;
}
This will create a new A. What if the signature of myFunc was
void myFunc(A a);
instead. Is there a syntax to create local instance inside the myFunc() parameter list? I'm looking for something like
myFunc(A());
or
myFunc(A a());
Another use would be for something like :
A a(123);
if(a == A(123)){ }
The net effect is to save one line, but it also creates a scope within the parameters list which makes me wonder if it is allowed at all.
If you just want to create a variable to pass to the function you can use a aggregate initialization / list initialization
#include <iostream>
#include <cmath>
using namespace std;
class A{ /*... snip ...*/ };
void myFunc(A a){ }
int main(){
myFunc(A{});
return 0;
}
Live Example
You can also use this with classes that have constructors that take multiple parameters
#include <iostream>
#include <cmath>
using namespace std;
class A
{
private:
int foo;
int bar;
double foobar;
public:
A(int a, int b, double c) : foo(a), bar(b), foobar(c) {}
};
void myFunc(A a){ }
int main(){
myFunc(A{1,2,3.0});
return 0;
}
Live Example
C++ supports this with the myFunc(A()); syntax you posed in your question.
#include <stdio.h>
char lazybuff[500];
class Point
{
public:
Point (double x, double y) : m_x(x), m_y(y) { }
char * ToString (void) { sprintf (lazybuff, "%f, %f", m_x, m_y); return lazybuff; }
private:
double m_x, m_y;
};
void print_point (Point print_me)
{
printf ("%s\n", print_me.ToString());
}
int main (void)
{
print_point (Point(5, 3));
return 0;
}

error C2280: attempting to reference a deleted function

I'm new to game development and very new to c++, but I've started developing a little Arkanoid game. I've had it running previously, but after refactoring (introducing the ArkanoidGame class) it doesnt compile and I cannot figure out why.
The error I'm getting is:
d:\dropbox\development\gamedev\c++\arkanoid\arkanoid\main.cpp(14): error C2280:
'ArkanoidGame::ArkanoidGame(void)' : attempting to reference a deleted function
d:\dropbox\development\gamedev\c++\arkanoid\arkanoid\arkanoidgame.h(25) :
compiler has generated 'ArkanoidGame::ArkanoidGame' here
I simply dont understand what this means and have no idea what to do to fix it.
I've included the classes in question:
Main.cpp:
#include "ArkanoidGame.h"
int main() {
ArkanoidGame game;
game.init(800, 600);
while (game.isRunning()) {
game.checkInput();
game.checkCollisions();
game.draw();
}
return 0;
}
Arkanoid.h:
#include "Ball.h"
#include "Pad.h"
#include <SFML/Graphics.hpp>
#include <stdarg.h>
#include <memory>
class ArkanoidGame
{
private:
bool running;
public:
void ArkanoidGame::init(int, int);
bool ArkanoidGame::isRunning();
void ArkanoidGame::checkCollisions();
void ArkanoidGame::checkInput();
void ArkanoidGame::update();
void ArkanoidGame::draw();
sf::RenderWindow* window;
Pad pad;
Ball ball;
};
ArkanoidGame.cpp:
#include "ArkanoidGame.h"
void ArkanoidGame::init(int windowWidth, int windowHeight) {
window = new sf::RenderWindow(sf::VideoMode(windowWidth, windowHeight), "Arkanoid!");
window->setFramerateLimit(60);
ArkanoidGame::running = true;
//Init pad
pad = Pad((float)(windowWidth / 2), (float)(windowHeight - 50));
//Init ball
ball = Ball(0.f, 0.f);
}
template<class T1, class T2> bool intersect(T1& mA, T2& mB) {
return mA.right() >= mB.left() && mA.left() <= mB.right()
&& mA.bottom() >= mB.top() && mA.top() <= mB.bottom();
}
void ArkanoidGame::checkCollisions() {
if (!intersect(pad, ball)) return;
ball.velocity.y = -ball.ballVelocity;
if (ball.x() < pad.x()) {
ball.velocity.x = -ball.ballVelocity;
}
else {
ball.velocity.x = ball.ballVelocity;
}
}
void ArkanoidGame::update() {
//Update positions
pad.update(window->getSize().x);
ball.update(window->getSize().x, window->getSize().y);
}
void ArkanoidGame::draw() {
window->clear(Color::Black);
window->draw(pad.getShape());
window->draw(ball.getShape());
window->display();
}
void ArkanoidGame::checkInput() {
if (Keyboard::isKeyPressed(Keyboard::Key::Escape)) {
running = false;
}
}
bool ArkanoidGame::isRunning() {
return running;
}
Presumably, either Pad or Ball (or both) has no default constructor; therefore one can't be generated for a class that contains them. They must be initialised using one of their declared constructors.
The best solution is to remove your weird init function, and replace it with a constructor:
ArkanoidGame(int windowWidth, int windowHeight) :
running(true),
window(new ...),
Pad(windowWidth / 2, windowHeight - 50),
Ball(0,0)
{
window->setFramerateLimit(60);
}
int main() {
ArkanoidGame game(800, 600);
// ...
}
If you really want a two-stage initialisation dance for some reason, then you'll need to provide default constructors for both Pad and Ball. I wouldn't recommend that though; there's less scope for errors if an object can't be created in an invalid state.
I think that the problem is that either class Pad or class Ball has no the default constructor ( you have two dtat members of these classes in the class definition of ArkanoidGame: Pad pad; and Ball ball;)
. In this case the compiler defined the default constructor of class ArkanoidGame as deleted (otherwise it will be ill-formed). However in the first line of main
ArkanoidGame game;
you try to call the default constructor of class ArkanoidGame.
Take also into account that declarations of member functions shall have unqualified names in the class definition.
So for example this declaration
void ArkanoidGame::init(int, int);
is invalid. Shall be
void init(int, int);
You should provide a constructor for ArkanoidGame. In Arkanoid.h:
ArkanoidGame ();
In Arkanoid.cpp:
ArkanoidGame::ArkanoidGame ()
{
// it is better to initialize members in the constructor,
// although not strictlynecessary
running = false;
}