Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » OO timer

Credits go to Niunio for helping out!
This thread is locked; no one can reply to it. rss feed Print
OO timer
BackwardsDown
Member #8,018
November 2006

Hi,
I am working my way into Allegro (thanks to all the kind people here;D) and trying to understand OO, what I want to do is create my own timer-object, so I can easely manage allegro-timers.

Here is my code:

Timer.h:

1#ifndef _TIMER_H
2#define _TIMER_H
3 
4class Timer
5{
6 public:
7 Timer(int frequency); // Constructor
8 ~Timer(); // Destructor
9 
10 void increaseValue();
11 
12 private:
13 int itsValue;
14 int itsLifespan;
15 int itsFrequency;
16};
17 
18#endif

Timer.cpp:

1#include <allegro.h>
2 
3#include "timer.h"
4 
5// Constructor
6Timer::Timer(int frequency)
7{
8 itsFrequency = frequency;
9 
10 LOCK_VARIABLE(itsValue); //Used to set the timer - which regulates the game's
11 LOCK_FUNCTION(Timer::increaseValue);//speed.
12 install_int_ex(Timer::increaseValue, BPS_TO_TIMER(itsFrequency));//Set our BPS
13}
14 
15// Destructor
16Timer::~Timer()
17{}
18 
19void Timer::increaseValue()
20{
21 itsValue++;
22}

But when I try to compile this one, I get the following error:
timer.cpp:14: error: argument of type ‘void (Timer::)()’ does not match ‘void (*)()

Which is understandable, but I dont know how to solve this one:-/.

Milan Mimica
Member #3,877
September 2003
avatar

You must make Timer::increaseValue static.

BackwardsDown
Member #8,018
November 2006

But when I set it up like this:

static void Timer::increaseValue()
{
  itsValue++;
}
END_OF_FUNCTION(increaseValue);

It says:
timer.h:13: error: invalid use of member ‘Timer::itsValue’ in static member function

Niunio
Member #1,975
March 2002
avatar

Because static methods must use static properties only.

You should study Object Oriented Programming before to apply it, shouldn't you? ::)

-----------------
Current projects: Allegro.pas | MinGRo

Milan Mimica
Member #3,877
September 2003
avatar

Of course. You can only access static members from a static function.

BackwardsDown
Member #8,018
November 2006

I think you're right :P

goes to read the rest of the book, instead of only the basics

CGamesPlay
Member #2,559
July 2002
avatar

But, with install_param_int_ex, you can pass a void* parameter to that static function. If that void* parameter is a Timer*, you can do this:

static void Timer::increaseValue(void* parm) {
    Timer* t = (Timer*) parm;
    t->itsValue++;
}

--
Tomasu: Every time you read this: hugging!

Ryan Patterson - <http://cgamesplay.com/>

Simon Parzer
Member #3,330
March 2003
avatar

You shouldn't use C-style casting in C++...

//Timer* t = (Timer*) parm;
Timer* t = static_cast<Timer*>(parm);

But otherwise CGamesPlay is right. Making a static method which takes a pointer to an object of the class is the usual approach for such problems (providing function callbacks for C-APIs in C++).

ImLeftFooted
Member #3,935
October 2003
avatar

Quote:

You shouldn't use C-style casting in C++...
//Timer* t = (Timer*) parm;
Timer* t = static_cast<Timer*>(parm);

Thats fugly. I prefer (Timer*) style cast.

Thomas Fjellstrom
Member #476
June 2000
avatar

And they are the same damn thing.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Simon Parzer
Member #3,330
March 2003
avatar

Quote:

And they are the same damn thing.

No. The C-style cast can have the effect of reinterpret_cast. static_cast ensures that the cast is possible, check is being performed at compile time.

ahmet yilmaz
Member #4,915
August 2004

Hey Miran did it before you. Copy from his masking lib.;D

ImLeftFooted
Member #3,935
October 2003
avatar

And both reinterpret_cast and static_cast will work. who'd a thunk it.

Stroustrup himself said the real reason for all those casts was to make casting an ugly operation that is hard to type. Stroustrup's ideal is a program with no casts.

I disagree with him, I integrate casts into my everyday life. Therefore i chose to ignore that part of his C++ standard.

CGamesPlay
Member #2,559
July 2002
avatar

Quote:

The C-style cast can have the effect of reinterpret_cast.

First and foremost, it doesn't in this case, without a doubt. Now, can you point out a case where it does?

--
Tomasu: Every time you read this: hugging!

Ryan Patterson - <http://cgamesplay.com/>

Simon Parzer
Member #3,330
March 2003
avatar

Quote:

First and foremost, it doesn't in this case, without a doubt. Now, can you point out a case where it does?

static void Timer::increaseValue(void* parm) {
    Timer* t = (Timer*) parm;
    t->itsValue++;
}

void evilFunction( )
{
  NotTimer nt;
  Timer::increaseValue((void*)&nt);
}

Tadaa! Runtime error.

Thomas Fjellstrom
Member #476
June 2000
avatar

using void in a C++ program is retarded (in most cases) to begin with, just don't.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Kitty Cat
Member #2,815
October 2002
avatar

So, it's bad because the user can craft a method to break it? Then reinterpret_cast<> is bad because the user can skip checking for a NULL (sorry, I mean 0) return, to cause a run-time error.

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

ImLeftFooted
Member #3,935
October 2003
avatar

Why would you ever ever pass the pointer to some random object to a function? No. you just dont.

You read the function's documentation and you figure out what the function needs. If you're not gonna do that you shouldn't be programming. At least not within 100 miles of me.

[edit]
If you're in the habit of passing pointers to random things to functions, then you're pretty evil. I wont put my coding standards around something in case i have to work with an evil coder.

[edit]
On second though, you're post doesn't quite make sense to me. Heres a modified version that works just as well.

Modified Version said:

static void Timer::increaseValue(void* parm) {
    Timer* t = reinterpret_cast(Timer*) parm; // static_cast will not compile here
    t->itsValue++;
}

void evilFunction( )
{
  NotTimer nt;
  Timer::increaseValue((void*)&nt);
}

Tadaa! Runtime error.

[edit]
Made my post less harsh sounding.

tobing
Member #5,213
November 2004
avatar

Just because it's possible to do bad things in a language, that doesn't mean you should. Most of that sort of constructs in C or C++ have their reason to exist, but shouldn't be used in general, except there's a very good reason to do so. And mostly, there are several ways to accomplish whatever is desired, so it's the programmer's task to choose the better ways whenever possible...

BackwardsDown
Member #8,018
November 2006

After reading a few chapters of my book I think I have achieved what I wanted to do.

Anyway, I just wanted to show you how I have done it:

1// Constructor
2Timer::Timer(int frequency)
3{
4 itsValue = 0;
5
6 itsFrequency = frequency;
7 
8 void (*pFunc)(void*);
9 pFunc = Timer::increaseValue;
10 Timer *param = this;
11 
12 LOCK_VARIABLE(itsValue); //Used to set the timer - which regulates the game's
13 LOCK_FUNCTION(pFunc);//speed.
14 install_param_int_ex(pFunc, this, BPS_TO_TIMER(itsFrequency));//Set our BPS
15}
16 
17void Timer::increaseValue(void* object) {
18 Timer* timer = (Timer*) object;
19 timer->itsValue++;
20}END_OF_FUNCTION(increaseValue);

Simon Parzer
Member #3,330
March 2003
avatar

Quote:

On second though, you're post doesn't quite make sense to me. Heres a modified version that works just as well.

Aww. Of course my "problem demonstration" code doesn't make much sense. I was just trying to point out that static_cast is NOT the same as normal C-style casting, which is the same as reinterpret_cast which is not as safe as static_cast, which in turn is not the same as normal C-style casting ... (endless loop)

Anyway, :-/
I suppose when you mess (or have to mess) with void pointers, it doesn't make much difference anymore, as static_cast only has advantages over reinterpret_cast when dealing with class hierarchies.

This also means that my first post in this thread didn't make much sense either.. sorry!

BackwardsDown
Member #8,018
November 2006

I is always good to see different vieuws on a problem:D

Indeterminatus
Member #737
November 2000
avatar

Quote:

I is always good to see different vieuws on a problem:D

I whole-heartedly disagree :P. While it can be good to get some incentives, in some places there just is no room for discussion, especially when working in a team. This of course requires all team members to be able to cut down their ego, or the whole thing collapses. Which is inevitable in either case, with a team of dogmatic members you are screwed anyway. What was my point? Oh yeah:

Quote:

It is sometimes good to see different views on a problem :D

Fixed.

Oh, and also, it is almost never good to derail a discussion and be nit-picky. Alas, my apologies for doing so.

_______________________________
Indeterminatus. [Atomic Butcher]
si tacuisses, philosophus mansisses

Simon Parzer
Member #3,330
March 2003
avatar

Quote:

I whole-heartedly disagree :P. While it can be good to get some incentives, in some places there just is no room for discussion, especially when working in a team. This of course requires all team members to be able to cut down their ego, or the whole thing collapses.

Yeah. I experienced this several times. Either the whole thing collapses or one person takes over and does everything alone.

Go to: