2

I am trying to create a speed distance and time calculator that is as efficient as possible and would like to refer to call a function using a pointer that changes according to input but am not sure how to do so. I have tried many different things:

My best attempt:

// Inside class Math
double calcSpeed(double distance, double time); // These functions return a double value of the formula (non static)
double calcDistance(double speed, double time);
double calcTime(double speed, double distance);

// Inside Main
typedef double (Math::*FuncChosen)(double first, double second);
FuncChosen p = &Math::calcSpeed; // This changes according to input to different functions in Math class with same parameter types and return types
p(1, 2); // Not a function, how can I non explicitly call the function?

Is there a way to call this function without explicitly referring to it using pointers or otherwise. Like calling a function from a pointer that changes according to input? I don't really know where to start and what to use as everything I try is illegal. I basically want to chose the function at runtime without using several ifs and thus avoiding repetition. (I have found people with similar problems but haven't found an efficient way of doing it for my purpose.)

Thanks in advance,

And, yes, I am new to C++ and haven't done much with pointers/references and memory.

Edit: For reference, the finished, complete code after corrections - compilable

exitcode
  • 111
  • 4
  • 12
  • Why not make the functions in Math class static, or not have them in a class at all? (They can still be in a namespace) – Neil Kirk Oct 28 '14 at 14:44
  • Wow, I keep getting const and static confused. I guess I probably could have made them static but I guess I thought I should know this anyway. I guess leaving them not-static means I have more flexibility? Also, this was basically a project to incorporate several different thinks that I had learnt so I wanted to put it in a separate class partly for this reason and also to look a little cleaner. tl;dr: I probably could have done one of those things but at some point I would have to find this out anyway. – exitcode Oct 28 '14 at 14:52
  • The only thing in Math they need is a string stream but I'm not sure what it's used for. Make Math a namespace and remove the stream. – Neil Kirk Oct 28 '14 at 15:14
  • String stream is to combine doubles and strings so I can print out working – exitcode Oct 28 '14 at 17:38

2 Answers2

5

You haven't included an MCVE, but the comments and code indicate the functions are non-static member functions inside class Math. The type FuncChosen is a pointer to member function.

Pointers to members are weird beasts. It's not really a pointer, as it doesn't point to anything directly. Think of a pointer to member as an "identifier within the class." So, p identifies a particular member function (such as calcSpeed). Just as you can normally call a member function only by calling it on an object, you need to supply an object to call through the pointer to member. So, for example, if you have this code:

Math m;
double res = m.calcSpeed(1.0, 2.0);

Then the equivalent with the pointer-to-member p would be:

Math m;
FuncChosen p = &Math::calcSpeed;
(m.*p)(1.0, 2.0);

The operator .* (and the corresponding ->*) are used to dereference a pointer to member.


For completeness: The above applies to non-static member functions. If calcSpeed etc. were static member functions instead, you would use normal pointers to functions to refer to them.

Community
  • 1
  • 1
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • Thanks for the answer and it seemed to work but, this is probably not a related issue, I just tried that and got these compiler errors: https://gist.github.com/exitcode/0948341a1557c27412f0 – exitcode Oct 28 '14 at 09:30
  • That's a different issue, and it calls for implementing the function `calcSpeed` itself. – Ajay Oct 28 '14 at 09:32
  • @SharkyDoesCode Yes, that's unrelated. It's not a compiler error, it's a linker error. It's complaining it doesn't have access to the definitions of the functions. Either you haven't defined them, or aren't linking in the object file containing them. You could find some help in [this FAQ question](http://stackoverflow.com/q/12573816/1782465). – Angew is no longer proud of SO Oct 28 '14 at 09:32
  • Ok thanks for the help, I had the functions under main and was referencing them from the Math class, redeclared them completely in Math class and now works. Thanks again for your answer @Angrew works perfectly. – exitcode Oct 28 '14 at 09:35
  • 1
    @SharkyDoesCode Then you probably had them defined as `double calcSpeed(double, double) { ... }`, which introduces an unrelated global function. To define a function outside its class, it has to be qualified: `double Math::calcSpeed(double, double) { ... }`. – Angew is no longer proud of SO Oct 28 '14 at 09:41
  • @Angrew that's exactly what I did, fixed now. – exitcode Oct 28 '14 at 09:42
  • @exitc0de That depends. What's "wi"? :-) – Angew is no longer proud of SO Nov 06 '14 at 07:43
  • @Angrew Whoops, I meant functions that return pairs, but I tried and works fine now. – exitcode Nov 06 '14 at 07:47
2

A non-static function cannot be called without an object. Answer this: can you call calcSpeed like this?

calcSpeed(10.4, 444.0);

No. Because it needs an object on left.

Math o;
o.calcSpeed(10.4, 444.0);

You can hold address to this method, but you must call it using the object:

(o.*p)(10.4, 444.0);

ADD

If the object is referred by a pointer (Math* po = &o;), the ->* operator needs to be used:

(po->*p)(10.4, 444.0);

Which is same as:

((*po).*p)(10.4, 444.0);
Ajay
  • 18,086
  • 12
  • 59
  • 105